Example #1
0
File: idl.c Project: MPlatform/mdb
/* Append sorted list b to sorted list a. The result is unsorted but
 * a[1] is the min of the result and a[a[0]] is the max.
 */
int bdb_idl_append( ID *a, ID *b )
{
	ID ida, idb, tmp, swap = 0;

	if ( BDB_IDL_IS_ZERO( b ) ) {
		return 0;
	}

	if ( BDB_IDL_IS_ZERO( a ) ) {
		BDB_IDL_CPY( a, b );
		return 0;
	}

	if ( b[0] == 1 ) {
		return bdb_idl_append_one( a, BDB_IDL_FIRST( b ));
	}

	ida = BDB_IDL_LAST( a );
	idb = BDB_IDL_LAST( b );
	if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ||
		a[0] + b[0] >= BDB_IDL_UM_MAX ) {
		a[2] = IDL_MAX( ida, idb );
		a[1] = IDL_MIN( a[1], b[1] );
		a[0] = NOID;
		return 0;
	}

	if ( ida > idb ) {
		swap = idb;
		a[a[0]] = idb;
		b[b[0]] = ida;
	}

	if ( b[1] < a[1] ) {
		tmp = a[1];
		a[1] = b[1];
	} else {
		tmp = b[1];
	}
	a[0]++;
	a[a[0]] = tmp;

	{
		int i = b[0] - 1;
		AC_MEMCPY(a+a[0]+1, b+2, i * sizeof(ID));
		a[0] += i;
	}
	if ( swap ) {
		b[b[0]] = swap;
	}
	return 0;
}
Example #2
0
File: idl.c Project: 1ack/Impala
/*
 * bdb_idl_notin - return a intersection ~b (or a minus b)
 */
int
bdb_idl_notin(
	ID	*a,
	ID	*b,
	ID *ids )
{
	ID ida, idb;
	ID cursora = 0, cursorb = 0;

	if( BDB_IDL_IS_ZERO( a ) ||
		BDB_IDL_IS_ZERO( b ) ||
		BDB_IDL_IS_RANGE( b ) )
	{
		BDB_IDL_CPY( ids, a );
		return 0;
	}

	if( BDB_IDL_IS_RANGE( a ) ) {
		BDB_IDL_CPY( ids, a );
		return 0;
	}

	ida = bdb_idl_first( a, &cursora ),
	idb = bdb_idl_first( b, &cursorb );

	ids[0] = 0;

	while( ida != NOID ) {
		if ( idb == NOID ) {
			/* we could shortcut this */
			ids[++ids[0]] = ida;
			ida = bdb_idl_next( a, &cursora );

		} else if ( ida < idb ) {
			ids[++ids[0]] = ida;
			ida = bdb_idl_next( a, &cursora );

		} else if ( ida > idb ) {
			idb = bdb_idl_next( b, &cursorb );

		} else {
			ida = bdb_idl_next( a, &cursora );
			idb = bdb_idl_next( b, &cursorb );
		}
	}

	return 0;
}
Example #3
0
File: idl.c Project: 1ack/Impala
/* Add one ID to an unsorted list. We ensure that the first element is the
 * minimum and the last element is the maximum, for fast range compaction.
 *   this means IDLs up to length 3 are always sorted...
 */
int bdb_idl_append_one( ID *ids, ID id )
{
	if (BDB_IDL_IS_RANGE( ids )) {
		/* if already in range, treat as a dup */
		if (id >= BDB_IDL_FIRST(ids) && id <= BDB_IDL_LAST(ids))
			return -1;
		if (id < BDB_IDL_FIRST(ids))
			ids[1] = id;
		else if (id > BDB_IDL_LAST(ids))
			ids[2] = id;
		return 0;
	}
	if ( ids[0] ) {
		ID tmp;

		if (id < ids[1]) {
			tmp = ids[1];
			ids[1] = id;
			id = tmp;
		}
		if ( ids[0] > 1 && id < ids[ids[0]] ) {
			tmp = ids[ids[0]];
			ids[ids[0]] = id;
			id = tmp;
		}
	}
	ids[0]++;
	if ( ids[0] >= BDB_IDL_UM_MAX ) {
		ids[0] = NOID;
		ids[2] = id;
	} else {
		ids[ids[0]] = id;
	}
	return 0;
}
Example #4
0
File: idl.c Project: 1ack/Impala
int bdb_idl_insert( ID *ids, ID id )
{
	unsigned x;

#if IDL_DEBUG > 1
	Debug( LDAP_DEBUG_ANY, "insert: %04lx at %d\n", (long) id, x, 0 );
	idl_dump( ids );
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	if (BDB_IDL_IS_RANGE( ids )) {
		/* if already in range, treat as a dup */
		if (id >= BDB_IDL_FIRST(ids) && id <= BDB_IDL_LAST(ids))
			return -1;
		if (id < BDB_IDL_FIRST(ids))
			ids[1] = id;
		else if (id > BDB_IDL_LAST(ids))
			ids[2] = id;
		return 0;
	}

	x = bdb_idl_search( ids, id );
	assert( x > 0 );

	if( x < 1 ) {
		/* internal error */
		return -2;
	}

	if ( x <= ids[0] && ids[x] == id ) {
		/* duplicate */
		return -1;
	}

	if ( ++ids[0] >= BDB_IDL_DB_MAX ) {
		if( id < ids[1] ) {
			ids[1] = id;
			ids[2] = ids[ids[0]-1];
		} else if ( ids[ids[0]-1] < id ) {
			ids[2] = id;
		} else {
			ids[2] = ids[ids[0]-1];
		}
		ids[0] = NOID;
	
	} else {
		/* insert id */
		AC_MEMCPY( &ids[x+1], &ids[x], (ids[0]-x) * sizeof(ID) );
		ids[x] = id;
	}

#if IDL_DEBUG > 1
	idl_dump( ids );
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	return 0;
}
Example #5
0
File: idl.c Project: 1ack/Impala
ID bdb_idl_first( ID *ids, ID *cursor )
{
	ID pos;

	if ( ids[0] == 0 ) {
		*cursor = NOID;
		return NOID;
	}

	if ( BDB_IDL_IS_RANGE( ids ) ) {
		if( *cursor < ids[1] ) {
			*cursor = ids[1];
		}
		return *cursor;
	}

	if ( *cursor == 0 )
		pos = 1;
	else
		pos = bdb_idl_search( ids, *cursor );

	if( pos > ids[0] ) {
		return NOID;
	}

	*cursor = pos;
	return ids[pos];
}
Example #6
0
File: idl.c Project: 1ack/Impala
static int bdb_idl_delete( ID *ids, ID id )
{
	unsigned x;

#if IDL_DEBUG > 1
	Debug( LDAP_DEBUG_ANY, "delete: %04lx at %d\n", (long) id, x, 0 );
	idl_dump( ids );
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	if (BDB_IDL_IS_RANGE( ids )) {
		/* If deleting a range boundary, adjust */
		if ( ids[1] == id )
			ids[1]++;
		else if ( ids[2] == id )
			ids[2]--;
		/* deleting from inside a range is a no-op */

		/* If the range has collapsed, re-adjust */
		if ( ids[1] > ids[2] )
			ids[0] = 0;
		else if ( ids[1] == ids[2] )
			ids[1] = 1;
		return 0;
	}

	x = bdb_idl_search( ids, id );
	assert( x > 0 );

	if( x <= 0 ) {
		/* internal error */
		return -2;
	}

	if( x > ids[0] || ids[x] != id ) {
		/* not found */
		return -1;

	} else if ( --ids[0] == 0 ) {
		if( x != 1 ) {
			return -3;
		}

	} else {
		AC_MEMCPY( &ids[x], &ids[x+1], (1+ids[0]-x) * sizeof(ID) );
	}

#if IDL_DEBUG > 1
	idl_dump( ids );
#elif IDL_DEBUG > 0
	idl_check( ids );
#endif

	return 0;
}
Example #7
0
File: idl.c Project: 1ack/Impala
static void idl_check( ID *ids )
{
	if( BDB_IDL_IS_RANGE( ids ) ) {
		assert( BDB_IDL_RANGE_FIRST(ids) <= BDB_IDL_RANGE_LAST(ids) );
	} else {
		ID i;
		for( i=1; i < ids[0]; i++ ) {
			assert( ids[i+1] > ids[i] );
		}
	}
}
Example #8
0
File: idl.c Project: 1ack/Impala
ID bdb_idl_next( ID *ids, ID *cursor )
{
	if ( BDB_IDL_IS_RANGE( ids ) ) {
		if( ids[2] < ++(*cursor) ) {
			return NOID;
		}
		return *cursor;
	}

	if ( ++(*cursor) <= ids[0] ) {
		return ids[*cursor];
	}

	return NOID;
}
Example #9
0
static void idl_dump( ID *ids )
{
	if( BDB_IDL_IS_RANGE( ids ) ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, INFO, "IDL: range (%ld - %ld)\n",
			(long) BDB_IDL_RANGE_FIRST( ids ),
			(long) BDB_IDL_RANGE_LAST( ids ), 0 );
#else
		Debug( LDAP_DEBUG_ANY,
			"IDL: range ( %ld - %ld )\n",
			(long) BDB_IDL_RANGE_FIRST( ids ),
			(long) BDB_IDL_RANGE_LAST( ids ) );
#endif

	} else {
		ID i;
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, INFO, "IDL: size %ld", (long) ids[0], 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0], 0, 0 );
#endif

		for( i=1; i<=ids[0]; i++ ) {
			if( i % 16 == 1 ) {
				Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
			}
#ifdef NEW_LOGGING
			LDAP_LOG( INDEX, INFO, "%02lx",(long)ids[i], 0, 0 );
#else
			Debug( LDAP_DEBUG_ANY, "  %02lx", (long) ids[i], 0, 0 );
#endif
		}

		Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
	}

	idl_check( ids );
}
Example #10
0
File: idl.c Project: 1ack/Impala
void
bdb_idl_cache_add_id(
	struct bdb_info	*bdb,
	DB			*db,
	DBT			*key,
	ID			id )
{
	bdb_idl_cache_entry_t *cache_entry, idl_tmp;
	DBT2bv( key, &idl_tmp.kstr );
	idl_tmp.db = db;
	ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
	cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
				      bdb_idl_entry_cmp );
	if ( cache_entry != NULL ) {
		if ( !BDB_IDL_IS_RANGE( cache_entry->idl ) &&
			cache_entry->idl[0] < BDB_IDL_DB_MAX ) {
			size_t s = BDB_IDL_SIZEOF( cache_entry->idl ) + sizeof(ID);
			cache_entry->idl = ch_realloc( cache_entry->idl, s );
		}
		bdb_idl_insert( cache_entry->idl, id );
	}
	ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
}
Example #11
0
File: idl.c Project: 1ack/Impala
static void idl_dump( ID *ids )
{
	if( BDB_IDL_IS_RANGE( ids ) ) {
		Debug( LDAP_DEBUG_ANY,
			"IDL: range ( %ld - %ld )\n",
			(long) BDB_IDL_RANGE_FIRST( ids ),
			(long) BDB_IDL_RANGE_LAST( ids ) );

	} else {
		ID i;
		Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0], 0, 0 );

		for( i=1; i<=ids[0]; i++ ) {
			if( i % 16 == 1 ) {
				Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
			}
			Debug( LDAP_DEBUG_ANY, "  %02lx", (long) ids[i], 0, 0 );
		}

		Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
	}

	idl_check( ids );
}
Example #12
0
int
hdb_dn2idl(
	Operation	*op,
	DB_TXN *txn,
	struct berval *ndn,
	EntryInfo	*ei,
	ID *ids,
	ID *stack )
{
	struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
	struct dn2id_cookie cx;

	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2idl(\"%s\")\n",
		ndn->bv_val, 0, 0 );

#ifndef BDB_MULTIPLE_SUFFIXES
	if ( op->ors_scope != LDAP_SCOPE_ONELEVEL && 
		( ei->bei_id == 0 ||
		( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len )))
	{
		BDB_IDL_ALL( bdb, ids );
		return 0;
	}
#endif

	cx.id = ei->bei_id;
	BDB_ID2DISK( cx.id, &cx.nid );
	cx.ei = ei;
	cx.bdb = bdb;
	cx.db = cx.bdb->bi_dn2id->bdi_db;
	cx.prefix = (op->ors_scope == LDAP_SCOPE_ONELEVEL) ?
		DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
	cx.ids = ids;
	cx.tmp = stack;
	cx.buf = stack + BDB_IDL_UM_SIZE;
	cx.op = op;
	cx.txn = txn;
	cx.need_sort = 0;
	cx.depth = 0;

	if ( cx.prefix == DN_SUBTREE_PREFIX ) {
		ids[0] = 1;
		ids[1] = cx.id;
	} else {
		BDB_IDL_ZERO( ids );
	}
	if ( cx.ei->bei_state & CACHE_ENTRY_NO_KIDS )
		return LDAP_SUCCESS;

	DBTzero(&cx.key);
	cx.key.ulen = sizeof(ID);
	cx.key.size = sizeof(ID);
	cx.key.flags = DB_DBT_USERMEM;

	DBTzero(&cx.data);

	hdb_dn2idl_internal(&cx);
	if ( cx.need_sort ) {
		char *ptr = ((char *)&cx.id)-1;
		if ( !BDB_IDL_IS_RANGE( cx.ids ) && cx.ids[0] > 3 ) 
			bdb_idl_sort( cx.ids, cx.tmp );
		cx.key.data = ptr;
		cx.key.size = sizeof(ID)+1;
		*ptr = cx.prefix;
		cx.id = ei->bei_id;
		if ( cx.bdb->bi_idl_cache_max_size )
			bdb_idl_cache_put( cx.bdb, cx.db, &cx.key, cx.ids, cx.rc );
	}

	if ( cx.rc == DB_NOTFOUND )
		cx.rc = LDAP_SUCCESS;

	return cx.rc;
}
Example #13
0
static int
hdb_dn2idl_internal(
	struct dn2id_cookie *cx
)
{
	BDB_IDL_ZERO( cx->tmp );

	if ( cx->bdb->bi_idl_cache_size ) {
		char *ptr = ((char *)&cx->id)-1;

		cx->key.data = ptr;
		cx->key.size = sizeof(ID)+1;
		if ( cx->prefix == DN_SUBTREE_PREFIX ) {
			ID *ids = cx->depth ? cx->tmp : cx->ids;
			*ptr = cx->prefix;
			cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, ids);
			if ( cx->rc == LDAP_SUCCESS ) {
				if ( cx->depth ) {
					bdb_idl_delete( cx->tmp, cx->id );	/* ITS#6983, drop our own ID */
					bdb_idl_append( cx->ids, cx->tmp );
					cx->need_sort = 1;
				}
				return cx->rc;
			}
		}
		*ptr = DN_ONE_PREFIX;
		cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
		if ( cx->rc == LDAP_SUCCESS ) {
			goto gotit;
		}
		if ( cx->rc == DB_NOTFOUND ) {
			return cx->rc;
		}
	}

	bdb_cache_entryinfo_lock( cx->ei );

	/* If number of kids in the cache differs from on-disk, load
	 * up all the kids from the database
	 */
	if ( cx->ei->bei_ckids+1 != cx->ei->bei_dkids ) {
		EntryInfo ei;
		db_recno_t dkids = cx->ei->bei_dkids;
		ei.bei_parent = cx->ei;

		/* Only one thread should load the cache */
		while ( cx->ei->bei_state & CACHE_ENTRY_ONELEVEL ) {
			bdb_cache_entryinfo_unlock( cx->ei );
			ldap_pvt_thread_yield();
			bdb_cache_entryinfo_lock( cx->ei );
			if ( cx->ei->bei_ckids+1 == cx->ei->bei_dkids ) {
				goto synced;
			}
		}

		cx->ei->bei_state |= CACHE_ENTRY_ONELEVEL;

		bdb_cache_entryinfo_unlock( cx->ei );

		cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,
			cx->bdb->bi_db_opflags );
		if ( cx->rc )
			goto done_one;

		cx->data.data = &cx->dbuf;
		cx->data.ulen = sizeof(ID);
		cx->data.dlen = sizeof(ID);
		cx->data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;

		/* The first item holds the parent ID. Ignore it. */
		cx->key.data = &cx->nid;
		cx->key.size = sizeof(ID);
		cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );
		if ( cx->rc ) {
			cx->dbc->c_close( cx->dbc );
			goto done_one;
		}

		/* If the on-disk count is zero we've never checked it.
		 * Count it now.
		 */
		if ( !dkids ) {
			cx->dbc->c_count( cx->dbc, &dkids, 0 );
			cx->ei->bei_dkids = dkids;
		}

		cx->data.data = cx->buf;
		cx->data.ulen = BDB_IDL_UM_SIZE * sizeof(ID);
		cx->data.flags = DB_DBT_USERMEM;

		if ( dkids > 1 ) {
			/* Fetch the rest of the IDs in a loop... */
			while ( (cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data,
				DB_MULTIPLE | DB_NEXT_DUP )) == 0 ) {
				u_int8_t *j;
				size_t len;
				void *ptr;
				DB_MULTIPLE_INIT( ptr, &cx->data );
				while (ptr) {
					DB_MULTIPLE_NEXT( ptr, &cx->data, j, len );
					if (j) {
						EntryInfo *ei2;
						diskNode *d = (diskNode *)j;
						short nrlen;

						BDB_DISK2ID( j + len - sizeof(ID), &ei.bei_id );
						nrlen = ((d->nrdnlen[0] ^ 0x80) << 8) | d->nrdnlen[1];
						ei.bei_nrdn.bv_len = nrlen;
						/* nrdn/rdn are set in-place.
						 * hdb_cache_load will copy them as needed
						 */
						ei.bei_nrdn.bv_val = d->nrdn;
						ei.bei_rdn.bv_len = len - sizeof(diskNode)
							- ei.bei_nrdn.bv_len;
						ei.bei_rdn.bv_val = d->nrdn + ei.bei_nrdn.bv_len + 1;
						bdb_idl_append_one( cx->tmp, ei.bei_id );
						hdb_cache_load( cx->bdb, &ei, &ei2 );
					}
				}
			}
		}

		cx->rc = cx->dbc->c_close( cx->dbc );
done_one:
		bdb_cache_entryinfo_lock( cx->ei );
		cx->ei->bei_state &= ~CACHE_ENTRY_ONELEVEL;
		bdb_cache_entryinfo_unlock( cx->ei );
		if ( cx->rc )
			return cx->rc;

	} else {
		/* The in-memory cache is in sync with the on-disk data.
		 * do we have any kids?
		 */
synced:
		cx->rc = 0;
		if ( cx->ei->bei_ckids > 0 ) {
			/* Walk the kids tree; order is irrelevant since bdb_idl_sort
			 * will sort it later.
			 */
			avl_apply( cx->ei->bei_kids, apply_func,
				cx->tmp, -1, AVL_POSTORDER );
		}
		bdb_cache_entryinfo_unlock( cx->ei );
	}

	if ( !BDB_IDL_IS_RANGE( cx->tmp ) && cx->tmp[0] > 3 )
		bdb_idl_sort( cx->tmp, cx->buf );
	if ( cx->bdb->bi_idl_cache_max_size && !BDB_IDL_IS_ZERO( cx->tmp )) {
		char *ptr = ((char *)&cx->id)-1;
		cx->key.data = ptr;
		cx->key.size = sizeof(ID)+1;
		*ptr = DN_ONE_PREFIX;
		bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
	}

gotit:
	if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
		if ( cx->prefix == DN_SUBTREE_PREFIX ) {
			bdb_idl_append( cx->ids, cx->tmp );
			cx->need_sort = 1;
			if ( !(cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS)) {
				ID *save, idcurs;
				EntryInfo *ei = cx->ei;
				int nokids = 1;
				save = cx->op->o_tmpalloc( BDB_IDL_SIZEOF( cx->tmp ),
					cx->op->o_tmpmemctx );
				BDB_IDL_CPY( save, cx->tmp );

				idcurs = 0;
				cx->depth++;
				for ( cx->id = bdb_idl_first( save, &idcurs );
					cx->id != NOID;
					cx->id = bdb_idl_next( save, &idcurs )) {
					EntryInfo *ei2;
					cx->ei = NULL;
					if ( bdb_cache_find_id( cx->op, cx->txn, cx->id, &cx->ei,
						ID_NOENTRY, NULL ))
						continue;
					if ( cx->ei ) {
						ei2 = cx->ei;
						if ( !( ei2->bei_state & CACHE_ENTRY_NO_KIDS )) {
							BDB_ID2DISK( cx->id, &cx->nid );
							hdb_dn2idl_internal( cx );
							if ( !BDB_IDL_IS_ZERO( cx->tmp ))
								nokids = 0;
						}
						bdb_cache_entryinfo_lock( ei2 );
						ei2->bei_finders--;
						bdb_cache_entryinfo_unlock( ei2 );
					}
				}
				cx->depth--;
				cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
				if ( nokids ) {
					bdb_cache_entryinfo_lock( ei );
					ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
					bdb_cache_entryinfo_unlock( ei );
				}
			}
			/* Make sure caller knows it had kids! */
			cx->tmp[0]=1;

			cx->rc = 0;
		} else {
			BDB_IDL_CPY( cx->ids, cx->tmp );
		}
	}
	return cx->rc;
}
Example #14
0
File: idl.c Project: 1ack/Impala
/*
 * idl_intersection - return a = a intersection b
 */
int
bdb_idl_intersection(
	ID *a,
	ID *b )
{
	ID ida, idb;
	ID idmax, idmin;
	ID cursora = 0, cursorb = 0, cursorc;
	int swap = 0;

	if ( BDB_IDL_IS_ZERO( a ) || BDB_IDL_IS_ZERO( b ) ) {
		a[0] = 0;
		return 0;
	}

	idmin = IDL_MAX( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) );
	idmax = IDL_MIN( BDB_IDL_LAST(a), BDB_IDL_LAST(b) );
	if ( idmin > idmax ) {
		a[0] = 0;
		return 0;
	} else if ( idmin == idmax ) {
		a[0] = 1;
		a[1] = idmin;
		return 0;
	}

	if ( BDB_IDL_IS_RANGE( a ) ) {
		if ( BDB_IDL_IS_RANGE(b) ) {
		/* If both are ranges, just shrink the boundaries */
			a[1] = idmin;
			a[2] = idmax;
			return 0;
		} else {
		/* Else swap so that b is the range, a is a list */
			ID *tmp = a;
			a = b;
			b = tmp;
			swap = 1;
		}
	}

	/* If a range completely covers the list, the result is
	 * just the list. If idmin to idmax is contiguous, just
	 * turn it into a range.
	 */
	if ( BDB_IDL_IS_RANGE( b )
		&& BDB_IDL_FIRST( b ) <= BDB_IDL_FIRST( a )
		&& BDB_IDL_LAST( b ) >= BDB_IDL_LAST( a ) ) {
		if (idmax - idmin + 1 == a[0])
		{
			a[0] = NOID;
			a[1] = idmin;
			a[2] = idmax;
		}
		goto done;
	}

	/* Fine, do the intersection one element at a time.
	 * First advance to idmin in both IDLs.
	 */
	cursora = cursorb = idmin;
	ida = bdb_idl_first( a, &cursora );
	idb = bdb_idl_first( b, &cursorb );
	cursorc = 0;

	while( ida <= idmax || idb <= idmax ) {
		if( ida == idb ) {
			a[++cursorc] = ida;
			ida = bdb_idl_next( a, &cursora );
			idb = bdb_idl_next( b, &cursorb );
		} else if ( ida < idb ) {
			ida = bdb_idl_next( a, &cursora );
		} else {
			idb = bdb_idl_next( b, &cursorb );
		}
	}
	a[0] = cursorc;
done:
	if (swap)
		BDB_IDL_CPY( b, a );

	return 0;
}
Example #15
0
File: idl.c Project: 1ack/Impala
void
bdb_idl_sort( ID *ids, ID *tmp )
{
	int count, soft_limit, phase = 0, size = ids[0];
	ID *idls[2];
	unsigned char *maxv = (unsigned char *)&ids[size];

 	if ( BDB_IDL_IS_RANGE( ids ))
 		return;

	/* Use insertion sort for small lists */
	if ( size <= SMALL ) {
		int i,j;
		ID a;

		for (j=1;j<=size;j++) {
			a = ids[j];
			for (i=j-1;i>=1;i--) {
				if (ids[i] <= a) break;
				ids[i+1] = ids[i];
			}
			ids[i+1] = a;
		}
		return;
	}

	tmp[0] = size;
	idls[0] = ids;
	idls[1] = tmp;

#if BYTE_ORDER == BIG_ENDIAN
    for (soft_limit = 0; !maxv[soft_limit]; soft_limit++);
#else
    for (soft_limit = sizeof(ID)-1; !maxv[soft_limit]; soft_limit--);
#endif

	for (
#if BYTE_ORDER == BIG_ENDIAN
	count = sizeof(ID)-1; count >= soft_limit; --count
#else
	count = 0; count <= soft_limit; ++count
#endif
	) {
		unsigned int num[BUCKETS], * np, n, sum;
		int i;
        ID *sp, *source, *dest;
        unsigned char *bp, *source_start;

		source = idls[phase]+1;
		dest = idls[phase^1]+1;
		source_start =  ((unsigned char *) source) + count;

        np = num;
        for ( i = BUCKETS; i > 0; --i ) *np++ = 0;

		/* count occurences of every byte value */
		bp = source_start;
        for ( i = size; i > 0; --i, bp += sizeof(ID) )
				num[*bp]++;

		/* transform count into index by summing elements and storing
		 * into same array
		 */
        sum = 0;
        np = num;
        for ( i = BUCKETS; i > 0; --i ) {
                n = *np;
                *np++ = sum;
                sum += n;
        }

		/* fill dest with the right values in the right place */
		bp = source_start;
        sp = source;
        for ( i = size; i > 0; --i, bp += sizeof(ID) ) {
                np = num + *bp;
                dest[*np] = *sp++;
                ++(*np);
        }
		phase ^= 1;
	}

	/* copy back from temp if needed */
	if ( phase ) {
		ids++; tmp++;
		for ( count = 0; count < size; ++count ) 
			*ids++ = *tmp++;
	}
}
Example #16
0
File: idl.c Project: 1ack/Impala
void
bdb_idl_sort( ID *ids, ID *tmp )
{
	int *istack = (int *)tmp;
	int i,j,k,l,ir,jstack;
	ID a, itmp;

	if ( BDB_IDL_IS_RANGE( ids ))
		return;

	ir = ids[0];
	l = 1;
	jstack = 0;
	for(;;) {
		if (ir - l < SMALL) {	/* Insertion sort */
			for (j=l+1;j<=ir;j++) {
				a = ids[j];
				for (i=j-1;i>=1;i--) {
					if (ids[i] <= a) break;
					ids[i+1] = ids[i];
				}
				ids[i+1] = a;
			}
			if (jstack == 0) break;
			ir = istack[jstack--];
			l = istack[jstack--];
		} else {
			k = (l + ir) >> 1;	/* Choose median of left, center, right */
			SWAP(ids[k], ids[l+1]);
			if (ids[l] > ids[ir]) {
				SWAP(ids[l], ids[ir]);
			}
			if (ids[l+1] > ids[ir]) {
				SWAP(ids[l+1], ids[ir]);
			}
			if (ids[l] > ids[l+1]) {
				SWAP(ids[l], ids[l+1]);
			}
			i = l+1;
			j = ir;
			a = ids[l+1];
			for(;;) {
				do i++; while(ids[i] < a);
				do j--; while(ids[j] > a);
				if (j < i) break;
				SWAP(ids[i],ids[j]);
			}
			ids[l+1] = ids[j];
			ids[j] = a;
			jstack += 2;
			if (ir-i+1 >= j-1) {
				istack[jstack] = ir;
				istack[jstack-1] = i;
				ir = j-1;
			} else {
				istack[jstack] = j-1;
				istack[jstack-1] = l;
				l = i;
			}
		}
	}
}
Example #17
0
File: idl.c Project: 1ack/Impala
/*
 * idl_union - return a = a union b
 */
int
bdb_idl_union(
	ID	*a,
	ID	*b )
{
	ID ida, idb;
	ID cursora = 0, cursorb = 0, cursorc;

	if ( BDB_IDL_IS_ZERO( b ) ) {
		return 0;
	}

	if ( BDB_IDL_IS_ZERO( a ) ) {
		BDB_IDL_CPY( a, b );
		return 0;
	}

	if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ) {
over:		ida = IDL_MIN( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) );
		idb = IDL_MAX( BDB_IDL_LAST(a), BDB_IDL_LAST(b) );
		a[0] = NOID;
		a[1] = ida;
		a[2] = idb;
		return 0;
	}

	ida = bdb_idl_first( a, &cursora );
	idb = bdb_idl_first( b, &cursorb );

	cursorc = b[0];

	/* The distinct elements of a are cat'd to b */
	while( ida != NOID || idb != NOID ) {
		if ( ida < idb ) {
			if( ++cursorc > BDB_IDL_UM_MAX ) {
				goto over;
			}
			b[cursorc] = ida;
			ida = bdb_idl_next( a, &cursora );

		} else {
			if ( ida == idb )
				ida = bdb_idl_next( a, &cursora );
			idb = bdb_idl_next( b, &cursorb );
		}
	}

	/* b is copied back to a in sorted order */
	a[0] = cursorc;
	cursora = 1;
	cursorb = 1;
	cursorc = b[0]+1;
	while (cursorb <= b[0] || cursorc <= a[0]) {
		if (cursorc > a[0])
			idb = NOID;
		else
			idb = b[cursorc];
		if (cursorb <= b[0] && b[cursorb] < idb)
			a[cursora++] = b[cursorb++];
		else {
			a[cursora++] = idb;
			cursorc++;
		}
	}

	return 0;
}