[Debtags-commits] [svn] r937 - in libtagcoll1/trunk: . tagcoll tests

Enrico Zini debtags-commits@lists.alioth.debian.org
Sat, 18 Jun 2005 22:32:46 +0000


Author: enrico
Date: Sat Jun 18 22:32:44 2005
New Revision: 937

Modified:
   libtagcoll1/trunk/README
   libtagcoll1/trunk/tagcoll/TDBDiskIndex.cc
   libtagcoll1/trunk/tagcoll/TDBDiskIndex.h
   libtagcoll1/trunk/tagcoll/TDBIndexer.cc
   libtagcoll1/trunk/tagcoll/TDBIndexer.h
   libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.cc
   libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.h
   libtagcoll1/trunk/tests/dump-tdbdi.cc
   libtagcoll1/trunk/tests/test-tdbdiskindex.cc
   libtagcoll1/trunk/tests/test-tdbindexer.cc
   libtagcoll1/trunk/tests/test-tdbreadonlydiskindex.cc
   libtagcoll1/trunk/tests/test-textformat.cc
Log:
Splid the index of TDBIndexes into one for tags and one for packages

Modified: libtagcoll1/trunk/README
==============================================================================
--- libtagcoll1/trunk/README	(original)
+++ libtagcoll1/trunk/README	Sat Jun 18 22:32:44 2005
@@ -104,6 +104,8 @@
 
 These are the TODO-list items currently being worked on::
 
+ + TDBDiskIndex: use two on-disk indexes: one for tag->item and one for
+   item->tag
  - Report a wishlist bug to libtool asking for a feature to generate PIC
    libraries
 

Modified: libtagcoll1/trunk/tagcoll/TDBDiskIndex.cc
==============================================================================
--- libtagcoll1/trunk/tagcoll/TDBDiskIndex.cc	(original)
+++ libtagcoll1/trunk/tagcoll/TDBDiskIndex.cc	Sat Jun 18 22:32:44 2005
@@ -37,11 +37,20 @@
 
 
 template<class ITEM, class TAG>
-TDBDiskIndex<ITEM, TAG>::TDBDiskIndex(const string& filename, Serializer<ITEM, TAG>& serializer, bool open)
-	throw (SystemException) : db(filename), serializer(serializer)
+TDBDiskIndex<ITEM, TAG>::TDBDiskIndex(
+		const string& pkgidx,
+		const string& tagidx,
+		Serializer<ITEM, TAG>& serializer, bool open)
+	throw (SystemException) :
+		pkgdb(pkgidx),
+		tagdb(tagidx),
+		serializer(serializer)
 {
 	if (open)
-		db.open(0, O_RDWR | O_CREAT);
+	{
+		pkgdb.open(0, O_RDWR | O_CREAT);
+		tagdb.open(0, O_RDWR | O_CREAT);
+	}
 }
 
 template<class ITEM, class TAG>
@@ -52,48 +61,48 @@
 template<class ITEM, class TAG>
 bool TDBDiskIndex<ITEM, TAG>::hasTag(const TAG& tag) const throw ()
 {
-	return db.has("T" + serializer.tagToString(tag));
+	return tagdb.has(serializer.tagToString(tag));
 }
 
 template<class ITEM, class TAG>
 bool TDBDiskIndex<ITEM, TAG>::hasItem(const ITEM& item) const throw ()
 {
-	return db.has("I" + serializer.itemToString(item));
+	return pkgdb.has(serializer.itemToString(item));
 }
 
 template<class ITEM, class TAG>
 OpSet<ITEM> TDBDiskIndex<ITEM, TAG>::getItems(const TAG& tag) const throw ()
 {
-	return serializer.stringsToItems(db.getStringSet("T" + serializer.tagToString(tag)));
+	return serializer.stringsToItems(tagdb.getStringSet(serializer.tagToString(tag)));
 }
 
 template<class ITEM, class TAG>
 OpSet<TAG> TDBDiskIndex<ITEM, TAG>::getTags(const ITEM& item) const throw ()
 {
-	return serializer.stringsToTags(db.getStringSet("I" + serializer.itemToString(item)));
+	return serializer.stringsToTags(pkgdb.getStringSet(serializer.itemToString(item)));
 }
 
 template<class ITEM, class TAG>
 OpSet<ITEM> TDBDiskIndex<ITEM, TAG>::getUntaggedItems() const throw ()
 {
-	return serializer.stringsToItems(db.getStringSet("T"));
+	return serializer.stringsToItems(tagdb.getStringSet(""));
 }
 
 static int collect_items(TDB_CONTEXT* db, TDB_DATA key, TDB_DATA val, void* data) throw ()
 {
-	if (key.dsize >= 1 && key.dptr[0] == 'I')
+	if (key.dsize >= 1)
 	{
 		OpSet<string>* coll = (OpSet<string>*)data;
-		(*coll) += string(key.dptr + 1, key.dsize - 1);
+		(*coll) += string(key.dptr, key.dsize);
 	}
 	return 0;
 }
 static int collect_tags(TDB_CONTEXT* db, TDB_DATA key, TDB_DATA val, void* data) throw ()
 {
-	if (key.dsize >= 1 && key.dptr[0] == 'T')
+	if (key.dsize >= 1)
 	{
 		OpSet<string>* coll = (OpSet<string>*)data;
-		(*coll) += string(key.dptr + 1, key.dsize - 1);
+		(*coll) += string(key.dptr, key.dsize);
 	}
 	return 0;
 }
@@ -102,7 +111,7 @@
 OpSet<ITEM> TDBDiskIndex<ITEM, TAG>::getAllItems() const throw (SystemException)
 {
 	OpSet<string> res;
-	db.traverse(collect_items, &res);
+	pkgdb.traverse(collect_items, &res);
 	return serializer.stringsToItems(res);
 }
 
@@ -110,7 +119,7 @@
 OpSet<TAG> TDBDiskIndex<ITEM, TAG>::getAllTags() const throw (SystemException)
 {
 	OpSet<string> res;
-	db.traverse(collect_tags, &res);
+	tagdb.traverse(collect_tags, &res);
 	return serializer.stringsToTags(res);
 }
 
@@ -127,11 +136,11 @@
 template<class ITEM, class TAG>
 static int outputter(TDB_CONTEXT* db, TDB_DATA key, TDB_DATA val, void* data) throw ()
 {
-	if (key.dsize >= 1 && key.dptr[0] == 'I')
+	if (key.dsize >= 1)
 	{
 		out_data<ITEM, TAG>* d = (out_data<ITEM, TAG>*)data;
 		// Deserialize the key into a string
-		string item(key.dptr + 1, key.dsize - 1);
+		string item(key.dptr, key.dsize);
 
 		// Deserialize the tags into a string list
 		OpSet<string> tags = TDBFile::deserialize_stringset(val);
@@ -148,7 +157,7 @@
 void TDBDiskIndex<ITEM, TAG>::output(TagcollConsumer<ITEM, TAG>& consumer) const throw (SystemException)
 {
 	out_data<ITEM, TAG> data(serializer, consumer);
-	db.traverse(outputter<ITEM, TAG>, &data);
+	pkgdb.traverse(outputter<ITEM, TAG>, &data);
 }
 
 template<class ITEM, class TAG>
@@ -165,27 +174,27 @@
 		OpSet<string> sprev_tags = serializer.tagsToStrings(prevTags);
 
 		// Set the new tagset in the item
-		db.setStringSet("I" + sitem, stags);
+		pkgdb.setStringSet(sitem, stags);
 
 		// Fix the itemsets in the involved tags
 		OpSet<string> t = sprev_tags - stags;
 		for (OpSet<string>::const_iterator j = t.begin(); j != t.end(); j++)
 		{
-			OpSet<string> items = db.getStringSet("T" + *j) - sitem;
+			OpSet<string> items = tagdb.getStringSet(*j) - sitem;
 			if (items.empty())
-				db.remove("T" + *j);
+				tagdb.remove(*j);
 			else
-				db.setStringSet("T" + *j, items);
+				tagdb.setStringSet(*j, items);
 		}
 		t = stags - sprev_tags;
 		for (OpSet<string>::const_iterator j  = t.begin(); j != t.end(); j++)
-			db.setStringSet("T" + *j, db.getStringSet("T" + *j) + sitem);
+			tagdb.setStringSet(*j, tagdb.getStringSet(*j) + sitem);
 
 		// Fix the "untagged items" element
 		if (stags.empty() && !sprev_tags.empty())
-			db.setStringSet("T", db.getStringSet("T") + sitem);
+			tagdb.setStringSet("", tagdb.getStringSet("") + sitem);
 		else if (sprev_tags.empty() && !stags.empty())
-			db.setStringSet("T", db.getStringSet("T") - sitem);
+			tagdb.setStringSet("", tagdb.getStringSet("") - sitem);
 	}
 }
 
@@ -194,14 +203,14 @@
 void TDBDiskIndex<ITEM, TAG>::consume(const ITEM& item) throw ()
 {
 	string sitem = serializer.itemToString(item);
-	OpSet<string> prev_stags = db.getStringSet("I" + sitem);
+	OpSet<string> prev_stags = pkgdb.getStringSet(sitem);
 
 	if (prev_stags.empty())
 	{
 		// Make the item at least exist
-		db.setStringSet("I" + sitem, prev_stags);
+		pkgdb.setStringSet(sitem, prev_stags);
 		// And add it to the "untagged" entry
-		db.setStringSet("T", db.getStringSet("T") + sitem);
+		tagdb.setStringSet("", tagdb.getStringSet("") + sitem);
 	}
 }
 
@@ -210,18 +219,18 @@
 {
 	string sitem = serializer.itemToString(item);
 	OpSet<string> stags = serializer.tagsToStrings(tags);
-	OpSet<string> prev_stags = db.getStringSet("I" + sitem);
+	OpSet<string> prev_stags = pkgdb.getStringSet(sitem);
 
 	// Add the tags to the item
-	db.setStringSet("I" + sitem, prev_stags + stags);
+	pkgdb.setStringSet(sitem, prev_stags + stags);
 
 	// Add the item to the tags
 	for (typename OpSet<string>::const_iterator i = stags.begin(); i != stags.end(); i++)
-		db.setStringSet("T" + *i, db.getStringSet("T" + *i) + sitem);
+		tagdb.setStringSet(*i, tagdb.getStringSet(*i) + sitem);
 
 	// Remove the item from the "untagged" entry
 	if (prev_stags.empty() && !stags.empty())
-		db.setStringSet("T", db.getStringSet("T") - sitem);
+		tagdb.setStringSet("", tagdb.getStringSet("") - sitem);
 }
 
 template<class ITEM, class TAG>
@@ -232,26 +241,26 @@
 
 	for (typename OpSet<string>::const_iterator i = sitems.begin(); i != sitems.end(); i++)
 		// Add the tags to the item
-		db.setStringSet("I" + *i, db.getStringSet("I" + *i) + stags);
+		pkgdb.setStringSet(*i, pkgdb.getStringSet(*i) + stags);
 
 	for (typename OpSet<string>::const_iterator i = stags.begin(); i != stags.end(); i++)
 		// Add the items to the tag
-		db.setStringSet("T" + *i, db.getStringSet("T" + *i) + sitems);
+		tagdb.setStringSet(*i, tagdb.getStringSet(*i) + sitems);
 
 	// Remove the items from the "untagged" entry
 	if (!stags.empty())
-		db.setStringSet("T", db.getStringSet("T") - sitems);
+		tagdb.setStringSet("", tagdb.getStringSet("") - sitems);
 }
 
 #ifndef INSTANTIATING_TEMPLATES
 OpSet<string> TDBDiskIndex<string, string>::getItems(const string& tag) const throw ()
 {
-	return db.getStringSet("T" + tag);
+	return tagdb.getStringSet(tag);
 }
 
 OpSet<string> TDBDiskIndex<string, string>::getTags(const string& item) const throw ()
 {
-	return db.getStringSet("I" + item);
+	return pkgdb.getStringSet(item);
 }
 
 #endif

Modified: libtagcoll1/trunk/tagcoll/TDBDiskIndex.h
==============================================================================
--- libtagcoll1/trunk/tagcoll/TDBDiskIndex.h	(original)
+++ libtagcoll1/trunk/tagcoll/TDBDiskIndex.h	Sat Jun 18 22:32:44 2005
@@ -46,7 +46,8 @@
 class TDBDiskIndex : public DiskIndex<ITEM, TAG>
 {
 protected:
-	TDBFile db;
+	TDBFile pkgdb;
+	TDBFile tagdb;
 	Serializer<ITEM, TAG>& serializer;
 
 public:
@@ -65,7 +66,8 @@
 	 *   class to open the index with different modes.
 	 */
 	TDBDiskIndex(
-			const std::string& filename,
+			const std::string& pkgidx,
+			const std::string& tagidx,
 			Serializer<ITEM, TAG>& serializer,
 			bool open = true)
 		throw (SystemException);

Modified: libtagcoll1/trunk/tagcoll/TDBIndexer.cc
==============================================================================
--- libtagcoll1/trunk/tagcoll/TDBIndexer.cc	(original)
+++ libtagcoll1/trunk/tagcoll/TDBIndexer.cc	Sat Jun 18 22:32:44 2005
@@ -63,23 +63,25 @@
 }
 
 template<class ITEM, class TAG>
-void TDBIndexer<ITEM, TAG>::writeIndex(const std::string& filename) throw ()
+void TDBIndexer<ITEM, TAG>::writeIndex(const std::string& pkgidx, const std::string& tagidx) throw ()
 {
 	TDB_CONTEXT* db;
 
-	db = tdb_open(filename.c_str(), 0, 0, O_RDWR | O_CREAT, 0666);
+	db = tdb_open(pkgidx.c_str(), 0, 0, O_RDWR | O_CREAT, 0666);
 	if (db == NULL)
-			throw SystemException(errno, "opening index file " + filename);
-
-	for (typename map<TAG, OpSet<ITEM> >::const_iterator i = tags.begin();
-			i != tags.end(); i++)
-		set_tdb(db, "T" + serializer.tagToString(i->first), serializer.itemsToStrings(i->second));
-
+			throw SystemException(errno, "opening index file " + pkgidx);
 	for (typename map<ITEM, OpSet<TAG> >::const_iterator i = items.begin();
 			i != items.end(); i++)
-		set_tdb(db, "I" + serializer.itemToString(i->first), serializer.tagsToStrings(i->second));
+		set_tdb(db, serializer.itemToString(i->first), serializer.tagsToStrings(i->second));
+	tdb_close(db);
 
-	set_tdb(db, "T", serializer.itemsToStrings(untagged));
+	db = tdb_open(tagidx.c_str(), 0, 0, O_RDWR | O_CREAT, 0666);
+	if (db == NULL)
+			throw SystemException(errno, "opening index file " + tagidx);
+	for (typename map<TAG, OpSet<ITEM> >::const_iterator i = tags.begin();
+			i != tags.end(); i++)
+		set_tdb(db, serializer.tagToString(i->first), serializer.itemsToStrings(i->second));
+	set_tdb(db, "", serializer.itemsToStrings(untagged));
 
 	tdb_close(db);
 }

Modified: libtagcoll1/trunk/tagcoll/TDBIndexer.h
==============================================================================
--- libtagcoll1/trunk/tagcoll/TDBIndexer.h	(original)
+++ libtagcoll1/trunk/tagcoll/TDBIndexer.h	Sat Jun 18 22:32:44 2005
@@ -110,7 +110,7 @@
 	/**
 	 * Write all collected informations to a disk index
 	 */
-	void writeIndex(const std::string& filename) throw ();
+	void writeIndex(const std::string& pkgidx, const std::string& tagidx) throw ();
 };
 
 };

Modified: libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.cc
==============================================================================
--- libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.cc	(original)
+++ libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.cc	Sat Jun 18 22:32:44 2005
@@ -35,13 +35,18 @@
 
 template<class ITEM, class TAG>
 TDBReadonlyDiskIndex<ITEM, TAG>::TDBReadonlyDiskIndex(
-		const string& filename,
+		const string& pkgidx,
+		const string& tagidx,
 		Serializer<ITEM, TAG>& serializer,
 		bool open)
-	throw (SystemException) : TDBDiskIndex<ITEM, TAG>(filename, serializer, false)
+	throw (SystemException) :
+		TDBDiskIndex<ITEM, TAG>(pkgidx, tagidx, serializer, false)
 {
 	if (open)
-		db.open(0, O_RDONLY);
+	{
+		pkgdb.open(0, O_RDONLY);
+		tagdb.open(0, O_RDONLY);
+	}
 }
 
 template<class ITEM, class TAG>
@@ -59,7 +64,7 @@
 	{
 		Patch<ITEM, TAG> newChange = i->second;
 
-		if (! db.has("I" + serializer.itemToString(i->first)))
+		if (! pkgdb.has(serializer.itemToString(i->first)))
 		{
 			newChange.removeRedundant(OpSet<TAG>());
 			this->changes.addPatch(newChange);
@@ -67,7 +72,7 @@
 		}
 		else
 		{
-			OpSet<TAG> tags = serializer.stringsToTags(db.getStringSet("I" + serializer.itemToString(i->first)));
+			OpSet<TAG> tags = serializer.stringsToTags(pkgdb.getStringSet(serializer.itemToString(i->first)));
 			newChange.removeRedundant(tags);
 			if (!newChange.getAdded().empty() || !newChange.getRemoved().empty())
 				this->changes.addPatch(newChange);
@@ -78,7 +83,7 @@
 template<class ITEM, class TAG>
 bool TDBReadonlyDiskIndex<ITEM, TAG>::hasItem(const ITEM& item) const throw ()
 {
-	if (! db.has("I" + serializer.itemToString(item)))
+	if (! pkgdb.has(serializer.itemToString(item)))
 		return newItems.contains(item); //changes.find(item) != changes.end();
 	else
 		return true;
@@ -87,7 +92,7 @@
 template<class ITEM, class TAG>
 bool TDBReadonlyDiskIndex<ITEM, TAG>::hasTag(const TAG& tag) const throw ()
 {
-	OpSet<ITEM> items = serializer.stringsToItems(db.getStringSet("T" + serializer.tagToString(tag)))
+	OpSet<ITEM> items = serializer.stringsToItems(tagdb.getStringSet(serializer.tagToString(tag)))
 		                + newItems;
 	for (typename OpSet<ITEM>::const_iterator i = items.begin();
 			i != items.end(); i++)
@@ -108,7 +113,7 @@
 template<class ITEM, class TAG>
 OpSet<ITEM> TDBReadonlyDiskIndex<ITEM, TAG>::getItems(const TAG& tag) const throw ()
 {
-	OpSet<ITEM> items = serializer.stringsToItems(db.getStringSet("T" + serializer.tagToString(tag)))
+	OpSet<ITEM> items = serializer.stringsToItems(tagdb.getStringSet(serializer.tagToString(tag)))
 	                    + newItems;
 	OpSet<ITEM> res;
 	for (typename OpSet<ITEM>::const_iterator i = items.begin();
@@ -128,7 +133,7 @@
 template<class ITEM, class TAG>
 OpSet<ITEM> TDBReadonlyDiskIndex<ITEM, TAG>::getUntaggedItems() const throw ()
 {
-	OpSet<ITEM> items = serializer.stringsToItems(db.getStringSet("T"))
+	OpSet<ITEM> items = serializer.stringsToItems(tagdb.getStringSet(""))
 		                + newItems;
 	OpSet<ITEM> res;
 	// Check for untagged items stored on disk
@@ -149,20 +154,20 @@
 template<class ITEM, class TAG>
 OpSet<TAG> TDBReadonlyDiskIndex<ITEM, TAG>::getTags(const ITEM& item) const throw ()
 {
-	OpSet<TAG> tags = changes.patch(item, serializer.stringsToTags(db.getStringSet("I" + serializer.itemToString(item))));
+	OpSet<TAG> tags = changes.patch(item, serializer.stringsToTags(pkgdb.getStringSet(serializer.itemToString(item))));
 	
 	// Also add tags of items introduced by the patch
-	tags += changes.patch(item, serializer.stringsToTags(db.getStringSet("I" + serializer.itemToString(item))));
+	tags += changes.patch(item, serializer.stringsToTags(pkgdb.getStringSet(serializer.itemToString(item))));
 
 	return tags;
 }
 
 static int tdbro_collect_items(TDB_CONTEXT* db, TDB_DATA key, TDB_DATA val, void* data) throw ()
 {
-	if (key.dsize >= 1 && key.dptr[0] == 'I')
+	if (key.dsize >= 1)
 	{
 		OpSet<string>* coll = (OpSet<string>*)data;
-		(*coll) += string(key.dptr + 1, key.dsize - 1);
+		(*coll) += string(key.dptr, key.dsize);
 	}
 	return 0;
 }
@@ -171,7 +176,7 @@
 OpSet<ITEM> TDBReadonlyDiskIndex<ITEM, TAG>::getAllItems() const throw (SystemException)
 {
 	OpSet<string> res;
-	db.traverse(tdbro_collect_items, &res);
+	pkgdb.traverse(tdbro_collect_items, &res);
 
 	OpSet<ITEM> items = serializer.stringsToItems(res) + newItems;
 
@@ -219,11 +224,11 @@
 template<class ITEM, class TAG>
 static int rfi_outputter(TDB_CONTEXT* db, TDB_DATA key, TDB_DATA val, void* data) throw ()
 {
-	if (key.dsize >= 1 && key.dptr[0] == 'I')
+	if (key.dsize >= 1)
 	{
 		out_patched_data<ITEM, TAG>* d = (out_patched_data<ITEM, TAG>*)data;
 		// Deserialize the key into a string
-		ITEM item = d->serializer.stringToItem(string(key.dptr + 1, key.dsize - 1));
+		ITEM item = d->serializer.stringToItem(string(key.dptr, key.dsize));
 		if (item != ITEM())
 		{
 			// Deserialize the tags into a string list
@@ -243,7 +248,7 @@
 void TDBReadonlyDiskIndex<ITEM, TAG>::output(TagcollConsumer<ITEM, TAG>& consumer) const throw (SystemException)
 {
 	out_patched_data<ITEM, TAG> data(serializer, consumer, changes, newItems);
-	db.traverse(rfi_outputter<ITEM, TAG>, &data);
+	pkgdb.traverse(rfi_outputter<ITEM, TAG>, &data);
 
 	// Also send the items that have been added after indexing
 	for (typename OpSet<ITEM>::const_iterator i = data.moreItems.begin();

Modified: libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.h
==============================================================================
--- libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.h	(original)
+++ libtagcoll1/trunk/tagcoll/TDBReadonlyDiskIndex.h	Sat Jun 18 22:32:44 2005
@@ -56,7 +56,8 @@
 	 *   class to open the index with different modes.
 	 */
 	TDBReadonlyDiskIndex(
-			const std::string& filename,
+			const std::string& pkgidx,
+			const std::string& tagidx,
 			Serializer<ITEM, TAG>& serializer,
 			bool open = true)
 		throw (SystemException);

Modified: libtagcoll1/trunk/tests/dump-tdbdi.cc
==============================================================================
--- libtagcoll1/trunk/tests/dump-tdbdi.cc	(original)
+++ libtagcoll1/trunk/tests/dump-tdbdi.cc	Sat Jun 18 22:32:44 2005
@@ -13,7 +13,7 @@
 		// Install the handler for unexpected exceptions
 		InstallUnexpected installUnexpected;
 		Serializer<string, string> serializer;
-		TDBReadonlyDiskIndex<string, string> coll(argv[1], serializer);
+		TDBReadonlyDiskIndex<string, string> coll(argv[1], argv[2], serializer);
 
 		TextFormat<string, string> writer(serializer, stdout);
 		coll.output(writer);

Modified: libtagcoll1/trunk/tests/test-tdbdiskindex.cc
==============================================================================
--- libtagcoll1/trunk/tests/test-tdbdiskindex.cc	(original)
+++ libtagcoll1/trunk/tests/test-tdbdiskindex.cc	Sat Jun 18 22:32:44 2005
@@ -41,10 +41,10 @@
 	template<> template<>
 	void to::test<1> ()
 	{
-		TrivialSerializer ser;
+		Serializer<string, string> ser;
 		try {
 			// An empty database should return empty sets, but not fail
-			Tagcoll::TDBDiskIndex<string, string> tfi("test.tdb", ser);
+			Tagcoll::TDBDiskIndex<string, string> tfi("testpkg.tdb", "testtag.tdb", ser);
 			gen_ensure(!tfi.hasItem("cippo"));
 			gen_ensure(!tfi.hasTag("cippo"));
 			gen_ensure(!tfi.hasItem("lippo"));
@@ -97,7 +97,7 @@
 
 		// Reopen the database to see if data is actually persisting
 		try {
-			Tagcoll::TDBDiskIndex<string, string> tfi("test.tdb", ser);
+			Tagcoll::TDBDiskIndex<string, string> tfi("testpkg.tdb", "testtag.tdb", ser);
 			Tagcoll::OpSet<string> s = tfi.getTags("cippo");
 
 			// Repeat the same queries: they should work
@@ -120,9 +120,9 @@
 	template<> template<>
 	void to::test<2> ()
 	{
-		TrivialSerializer ser;
+		Serializer<string, string> ser;
 		try {
-			Tagcoll::TDBDiskIndex<string, string> tfi("test.tdb", ser);
+			Tagcoll::TDBDiskIndex<string, string> tfi("testpkg.tdb", "testtag.tdb", ser);
 			test_tagged_collection(tfi);
 		} catch (Exception& e) {
 			fprintf(stderr, "%s: %.*s\n", e.type(), PFSTR(e.desc()));

Modified: libtagcoll1/trunk/tests/test-tdbindexer.cc
==============================================================================
--- libtagcoll1/trunk/tests/test-tdbindexer.cc	(original)
+++ libtagcoll1/trunk/tests/test-tdbindexer.cc	Sat Jun 18 22:32:44 2005
@@ -41,7 +41,7 @@
 	template<> template<>
 	void to::test<2> ()
 	{
-		TrivialSerializer ser;
+		Serializer<string, string> ser;
 		try {
 			Tagcoll::TDBIndexer<string, string> coll(ser);
 			test_tagged_collection(coll);

Modified: libtagcoll1/trunk/tests/test-tdbreadonlydiskindex.cc
==============================================================================
--- libtagcoll1/trunk/tests/test-tdbreadonlydiskindex.cc	(original)
+++ libtagcoll1/trunk/tests/test-tdbreadonlydiskindex.cc	Sat Jun 18 22:32:44 2005
@@ -40,16 +40,16 @@
 	template<> template<>
 	void to::test<1> ()
 	{
-		TrivialSerializer ser;
+		Serializer<string, string> ser;
 		PatchList<string, string> changes;
 		try {
 			{
 				// Create a real disk index
-				Tagcoll::TDBDiskIndex<string, string> di("test-ro.tdb", ser);
+				Tagcoll::TDBDiskIndex<string, string> di("test-ro-pkg.tdb", "test-ro-tag.tdb", ser);
 			}
 			
 			// An empty database should return empty sets, but not fail
-			Tagcoll::TDBReadonlyDiskIndex<string, string> tfi("test-ro.tdb", ser);
+			Tagcoll::TDBReadonlyDiskIndex<string, string> tfi("test-ro-pkg.tdb", "test-ro-tag.tdb", ser);
 			gen_ensure(!tfi.hasItem("cippo"));
 			gen_ensure(!tfi.hasTag("cippo"));
 			gen_ensure(!tfi.hasItem("lippo"));
@@ -107,7 +107,7 @@
 
 		// Reopen the database to see if data is actually persisting
 		try {
-			Tagcoll::TDBReadonlyDiskIndex<string, string> tfi("test-ro.tdb", ser);
+			Tagcoll::TDBReadonlyDiskIndex<string, string> tfi("test-ro-pkg.tdb", "test-ro-tag.tdb", ser);
 
 			/* Restore the patchlist */
 			tfi.setChanges(changes);
@@ -142,9 +142,9 @@
 	template<> template<>
 	void to::test<2> ()
 	{
-		TrivialSerializer ser;
+		Serializer<string, string> ser;
 		try {
-			Tagcoll::TDBReadonlyDiskIndex<string, string> tfi("test-ro.tdb", ser);
+			Tagcoll::TDBReadonlyDiskIndex<string, string> tfi("test-ro-pkg.tdb", "test-ro-tag.tdb", ser);
 			test_tagged_collection(tfi);
 		} catch (Exception& e) {
 			fprintf(stderr, "%s: %.*s\n", e.type(), PFSTR(e.desc()));

Modified: libtagcoll1/trunk/tests/test-textformat.cc
==============================================================================
--- libtagcoll1/trunk/tests/test-textformat.cc	(original)
+++ libtagcoll1/trunk/tests/test-textformat.cc	Sat Jun 18 22:32:44 2005
@@ -51,6 +51,12 @@
 		else
 			this->data = 0;
 	}
+	Item(const std::string& data) {
+		if (data.empty())
+			this->data = 0;
+		else
+			this->data = strdup(data.c_str());
+	}
 	Item(const Item& i) : data(i.data) {}
 	Item& operator=(const Item& i) { data = i.data; return *this; }
 	bool operator==(const Item& ns) const throw ()
@@ -72,48 +78,84 @@
 		return strcmp(data, ns.data) < 0;
 	}
 	operator bool() const throw () { return data != 0; }
+	operator std::string() const throw () { return data == 0 ? string() : string(data); }
 	string getData() const throw () { return string(data); }
 };
 
-template class OpSet<Item>;
-template class TagcollConsumer<Item, Item>;
-template class Serializer<Item, Item>;
-template class FromStrings<Item, Item>;
-template class ToStrings<Item, Item>;
-template class Patch<Item, Item>;
-template class PatchList<Item, Item>;
-template class DiskIndex<Item, Item>;
-template class TDBIndexer<Item, Item>;
-
-
 // Serializer to use for testing (can return NULL values)
-class ItemSerializer : public Serializer<Item, Item>
+namespace Tagcoll {
+template<>
+class Serializer<Item, Item>
 {
 public:
-	virtual std::string tagToString(const Item& tag) throw ()
+	std::string tagToString(const Item& tag) throw ()
 	{
 		return tag.getData();
 	}
 
-	virtual std::string itemToString(const Item& item) throw ()
+	std::string itemToString(const Item& item) throw ()
 	{
 		return item.getData();
 	}
 
-	virtual Item stringToTag(const std::string& tag) throw ()
+	Item stringToTag(const std::string& tag) throw ()
 	{
 		if (tag == "null")
 			return Item(0);
 		return Item(tag.c_str());
 	}
 
-	virtual Item stringToItem(const std::string& item) throw ()
+	Item stringToItem(const std::string& item) throw ()
 	{
 		if (item == "null")
 			return Item(0);
 		return Item(item.c_str());
 	}
+	OpSet<std::string> tagsToStrings(const OpSet<Item>& tags) throw ()
+	{
+		OpSet<string> res;
+		for (OpSet<Item>::const_iterator i = tags.begin();
+				i != tags.end(); i++)
+			res += tagToString(*i);
+		return res;
+	}
+	OpSet<std::string> itemsToStrings(const OpSet<Item>& items) throw ()
+	{
+		OpSet<string> res;
+		for (OpSet<Item>::const_iterator i = items.begin();
+				i != items.end(); i++)
+			res += itemToString(*i);
+		return res;
+	}
+	OpSet<Item> stringsToTags(const OpSet<std::string>& tags) throw ()
+	{
+		OpSet<Item> res;
+		for (OpSet<string>::const_iterator i = tags.begin();
+				i != tags.end(); i++)
+			res += stringToTag(*i);
+		return res;
+	}
+	OpSet<Item> stringsToItems(const OpSet<std::string>& items) throw ()
+	{
+		OpSet<Item> res;
+		for (OpSet<string>::const_iterator i = items.begin();
+				i != items.end(); i++)
+			res += stringToItem(*i);
+		return res;
+	}
 };
+};
+
+template class OpSet<Item>;
+template class TagcollConsumer<Item, Item>;
+template class Serializer<Item, Item>;
+//template class FromStrings<Item, Item>;
+//template class ToStrings<Item, Item>;
+template class Patch<Item, Item>;
+template class PatchList<Item, Item>;
+template class DiskIndex<Item, Item>;
+template class TDBIndexer<Item, Item>;
+
 
 class ItemChecker : public TagcollConsumer<Item, Item>
 {
@@ -174,7 +216,7 @@
 	template<> template<>
 	void to::test<1> ()
 	{
-		ItemSerializer ser;
+		Serializer<Item, Item> ser;
 		try {
 			// Parse the sample collection
 			StringParserInput in0(testCollection);
@@ -207,7 +249,7 @@
 	template<> template<>
 	void to::test<2> ()
 	{
-		ItemSerializer ser;
+		Serializer<Item, Item> ser;
 		try {
 			// Parse the sample patch
 			StringParserInput in0(testPatch);