summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2005-11-08 00:13:52 +0000
committerBernard Normier <bernard@zeroc.com>2005-11-08 00:13:52 +0000
commit20c342c1c5f35fbe60565dee7fb81ca2baf04e5b (patch)
tree199faf2102026478de9a1e55f6fff271591e7b98 /cpp/src
parentfixed bi-dir/shutdown deadlock (diff)
downloadice-20c342c1c5f35fbe60565dee7fb81ca2baf04e5b.tar.bz2
ice-20c342c1c5f35fbe60565dee7fb81ca2baf04e5b.tar.xz
ice-20c342c1c5f35fbe60565dee7fb81ca2baf04e5b.zip
Implemented enhancement 415 (Freeze Map compare functors)
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Freeze/MapI.cpp287
-rw-r--r--cpp/src/Freeze/MapI.h19
-rw-r--r--cpp/src/Freeze/SharedDb.cpp29
-rw-r--r--cpp/src/Freeze/SharedDb.h23
-rw-r--r--cpp/src/slice2freeze/Main.cpp422
5 files changed, 682 insertions, 98 deletions
diff --git a/cpp/src/Freeze/MapI.cpp b/cpp/src/Freeze/MapI.cpp
index f9473110012..065a48c1fa0 100644
--- a/cpp/src/Freeze/MapI.cpp
+++ b/cpp/src/Freeze/MapI.cpp
@@ -27,7 +27,10 @@ Freeze::MapIndexBase::~MapIndexBase()
{
}
-Freeze::MapIndexBase::MapIndexBase(const string& name) :
+Freeze::MapIndexBase::MapIndexBase(
+ const string& name,
+ bool enabled) :
+ KeyCompareBase(enabled),
_name(name),
_impl(0),
_map(0)
@@ -41,9 +44,21 @@ MapIndexBase::name() const
}
IteratorHelper*
-Freeze::MapIndexBase::untypedFind(const Key& k, bool ro) const
+Freeze::MapIndexBase::untypedFind(const Key& k, bool ro, bool onlyDups) const
{
- return _impl->untypedFind(k, ro, *_map);
+ return _impl->untypedFind(k, ro, *_map, onlyDups);
+}
+
+IteratorHelper*
+Freeze::MapIndexBase::untypedLowerBound(const Key& k, bool ro) const
+{
+ return _impl->untypedLowerBound(k, ro, *_map);
+}
+
+IteratorHelper*
+Freeze::MapIndexBase::untypedUpperBound(const Key& k, bool ro) const
+{
+ return _impl->untypedUpperBound(k, ro, *_map);
}
int
@@ -53,6 +68,19 @@ Freeze::MapIndexBase::untypedCount(const Key& k) const
}
//
+// KeyCompareBase
+//
+Freeze::KeyCompareBase::KeyCompareBase(bool enabled) :
+ _enabled(enabled)
+{}
+
+bool
+Freeze::KeyCompareBase::compareEnabled() const
+{
+ return _enabled;
+}
+
+//
// MapHelper (from Map.h)
//
@@ -61,11 +89,12 @@ Freeze::MapHelper::create(const Freeze::ConnectionPtr& connection,
const string& dbName,
const string& key,
const string& value,
+ const Freeze::KeyCompareBasePtr& keyCompare,
const std::vector<MapIndexBasePtr>& indices,
bool createDb)
{
Freeze::ConnectionIPtr connectionI = Freeze::ConnectionIPtr::dynamicCast(connection);
- return new MapHelperI(connectionI, dbName, key, value, indices, createDb);
+ return new MapHelperI(connectionI, dbName, key, value, keyCompare, indices, createDb);
}
Freeze::MapHelper::~MapHelper()
@@ -82,7 +111,8 @@ Freeze::IteratorHelper::create(const MapHelper& m, bool readOnly)
{
const MapHelperI& actualMap = dynamic_cast<const MapHelperI&>(m);
- auto_ptr<IteratorHelperI> r(new IteratorHelperI(actualMap, readOnly, 0));
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(actualMap, readOnly,
+ 0, false));
if(r->next())
{
return r.release();
@@ -104,11 +134,13 @@ Freeze::IteratorHelper::~IteratorHelper()
//
Freeze::IteratorHelperI::IteratorHelperI(const MapHelperI& m, bool readOnly,
- const MapIndexBasePtr& index) :
+ const MapIndexBasePtr& index,
+ bool onlyDups) :
_map(m),
_dbc(0),
_indexed(index != 0),
- _tx(0)
+ _tx(0),
+ _onlyDups(onlyDups)
{
if(_map._trace >= 2)
{
@@ -157,7 +189,8 @@ Freeze::IteratorHelperI::IteratorHelperI(const IteratorHelperI& it) :
_map(it._map),
_dbc(0),
_indexed(it._indexed),
- _tx(0)
+ _tx(0),
+ _onlyDups(it._onlyDups)
{
if(_map._trace >= 2)
{
@@ -228,6 +261,85 @@ Freeze::IteratorHelperI::find(const Key& key) const
}
}
+bool
+Freeze::IteratorHelperI::lowerBound(const Key& key) const
+{
+ //
+ // We retrieve the action key for upperBound
+ //
+ Dbt dbKey;
+ _key = key;
+ initializeOutDbt(_key, dbKey);
+ dbKey.set_size(static_cast<u_int32_t>(_key.size()));
+
+ //
+ // Keep 0 length since we're not interested in the data
+ //
+ Dbt dbValue;
+ dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
+
+ for(;;)
+ {
+ try
+ {
+ int err = _dbc->get(&dbKey, &dbValue, DB_SET_RANGE);
+ if(err == 0)
+ {
+ _key.resize(dbKey.get_size());
+ return true;
+ }
+ else if(err == DB_NOTFOUND)
+ {
+ return false;
+ }
+ else
+ {
+ //
+ // Bug in Freeze
+ //
+ assert(0);
+ throw DatabaseException(__FILE__, __LINE__);
+ }
+ }
+ catch(const ::DbDeadlockException& dx)
+ {
+ if(_tx != 0)
+ {
+ _tx->dead();
+ }
+
+ DeadlockException ex(__FILE__, __LINE__);
+ ex.message = dx.what();
+ throw ex;
+ }
+ catch(const ::DbException& dx)
+ {
+ handleDbException(dx, _key, dbKey, __FILE__, __LINE__);
+ }
+ }
+}
+
+bool
+Freeze::IteratorHelperI::upperBound(const Key& key) const
+{
+ if(lowerBound(key))
+ {
+ if(_key == key)
+ {
+ return next(true);
+ }
+ else
+ {
+ return true;
+ }
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
Freeze::IteratorHelper*
Freeze::IteratorHelperI::clone() const
{
@@ -478,9 +590,15 @@ Freeze::IteratorHelperI::erase()
}
}
-bool
+bool
Freeze::IteratorHelperI::next() const
{
+ return next(false);
+}
+
+bool
+Freeze::IteratorHelperI::next(bool skipDups) const
+{
//
// Keep 0 length since we're not interested in the data
//
@@ -489,7 +607,15 @@ Freeze::IteratorHelperI::next() const
Dbt dbValue;
dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
- int flags = _indexed ? DB_NEXT_DUP : DB_NEXT;
+ int flags = DB_NEXT;
+ if(skipDups)
+ {
+ flags = DB_NEXT_NODUP;
+ }
+ else if(_indexed && _onlyDups)
+ {
+ flags = DB_NEXT_DUP;
+ }
try
{
@@ -660,10 +786,11 @@ Freeze::MapHelperI::MapHelperI(const ConnectionIPtr& connection,
const string& dbName,
const string& key,
const string& value,
+ const KeyCompareBasePtr& keyCompare,
const vector<MapIndexBasePtr>& indices,
bool createDb) :
_connection(connection),
- _db(SharedDb::get(connection, dbName, key, value, indices, createDb)),
+ _db(SharedDb::get(connection, dbName, key, value, keyCompare, indices, createDb)),
_dbName(dbName),
_trace(connection->trace())
{
@@ -698,7 +825,7 @@ Freeze::MapHelperI::find(const Key& k, bool readOnly) const
{
try
{
- auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0));
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0, false));
if(r->find(k))
{
return r.release();
@@ -731,6 +858,86 @@ Freeze::MapHelperI::find(const Key& k, bool readOnly) const
}
}
+Freeze::IteratorHelper*
+Freeze::MapHelperI::lowerBound(const Key& k, bool readOnly) const
+{
+ for(;;)
+ {
+ try
+ {
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0, false));
+ if(r->lowerBound(k))
+ {
+ return r.release();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ catch(const DeadlockException&)
+ {
+ if(_connection->dbTxn() != 0)
+ {
+ throw;
+ }
+ else
+ {
+ if(_connection->deadlockWarning())
+ {
+ Warning out(_connection->communicator()->getLogger());
+ out << "Deadlock in Freeze::MapHelperI::lowerBound on Map \""
+ << _dbName << "\"; retrying ...";
+ }
+
+ //
+ // Ignored, try again
+ //
+ }
+ }
+ }
+}
+
+Freeze::IteratorHelper*
+Freeze::MapHelperI::upperBound(const Key& k, bool readOnly) const
+{
+ for(;;)
+ {
+ try
+ {
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0, false));
+ if(r->upperBound(k))
+ {
+ return r.release();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ catch(const DeadlockException&)
+ {
+ if(_connection->dbTxn() != 0)
+ {
+ throw;
+ }
+ else
+ {
+ if(_connection->deadlockWarning())
+ {
+ Warning out(_connection->communicator()->getLogger());
+ out << "Deadlock in Freeze::MapHelperI::upperBound on Map \""
+ << _dbName << "\"; retrying ...";
+ }
+
+ //
+ // Ignored, try again
+ //
+ }
+ }
+ }
+}
+
void
Freeze::MapHelperI::put(const Key& key, const Value& value)
{
@@ -1144,6 +1351,20 @@ Freeze::MapHelperI::closeAllIteratorsExcept(const IteratorHelperI::TxPtr& tx) co
// MapIndexI
//
+extern "C"
+{
+static int customIndexCompare(DB* db, const DBT* dbt1, const DBT* dbt2)
+{
+ MapIndexI* me = static_cast<MapIndexI*>(db->app_private);
+ Byte* first = static_cast<Byte*>(dbt1->data);
+ Key k1(first, first + dbt1->size);
+ first = static_cast<Byte*>(dbt2->data);
+ Key k2(first, first + dbt2->size);
+
+ return me->getKeyCompare()->compare(k1, k2);
+}
+}
+
static int
callback(Db* secondary, const Dbt* key, const Dbt* value, Dbt* result)
{
@@ -1172,6 +1393,13 @@ Freeze::MapIndexI::MapIndexI(const ConnectionIPtr& connection, SharedDb& db,
_dbName = db.dbName() + "." + _index->name();
+ _db->set_app_private(this);
+
+ if(index->compareEnabled())
+ {
+ _db->set_bt_compare(&customIndexCompare);
+ }
+
_db->open(txn, _dbName.c_str(), 0, DB_BTREE, flags, FREEZE_DB_MODE);
//
@@ -1191,9 +1419,10 @@ Freeze::MapIndexI::~MapIndexI()
}
IteratorHelper*
-Freeze::MapIndexI::untypedFind(const Key& k, bool ro, const MapHelperI& m) const
+Freeze::MapIndexI::untypedFind(const Key& k, bool ro, const MapHelperI& m,
+ bool onlyDups) const
{
- auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index));
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index, onlyDups));
if(r->find(k))
{
@@ -1205,6 +1434,36 @@ Freeze::MapIndexI::untypedFind(const Key& k, bool ro, const MapHelperI& m) const
}
}
+IteratorHelper*
+Freeze::MapIndexI::untypedLowerBound(const Key& k, bool ro, const MapHelperI& m) const
+{
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index, false));
+
+ if(r->lowerBound(k))
+ {
+ return r.release();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+IteratorHelper*
+Freeze::MapIndexI::untypedUpperBound(const Key& k, bool ro, const MapHelperI& m) const
+{
+ auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index, false));
+
+ if(r->upperBound(k))
+ {
+ return r.release();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
int
Freeze::MapIndexI::untypedCount(const Key& k, const ConnectionIPtr& connection) const
{
diff --git a/cpp/src/Freeze/MapI.h b/cpp/src/Freeze/MapI.h
index 5a1a1d9d9a0..8f842926a47 100644
--- a/cpp/src/Freeze/MapI.h
+++ b/cpp/src/Freeze/MapI.h
@@ -23,7 +23,8 @@ class IteratorHelperI : public IteratorHelper
{
public:
- IteratorHelperI(const MapHelperI& m, bool readOnly, const MapIndexBasePtr& index);
+ IteratorHelperI(const MapHelperI& m, bool readOnly,
+ const MapIndexBasePtr& index, bool onlyDups);
IteratorHelperI(const IteratorHelperI&);
virtual
@@ -32,6 +33,12 @@ public:
bool
find(const Key& k) const;
+ bool
+ lowerBound(const Key& k) const;
+
+ bool
+ upperBound(const Key& k) const;
+
virtual IteratorHelper*
clone() const;
@@ -50,6 +57,8 @@ public:
virtual bool
next() const;
+ bool next(bool) const;
+
void
close();
@@ -86,6 +95,7 @@ private:
const MapHelperI& _map;
Dbc* _dbc;
const bool _indexed;
+ const bool _onlyDups;
TxPtr _tx;
mutable Key _key;
@@ -99,6 +109,7 @@ public:
MapHelperI(const ConnectionIPtr&, const std::string&,
const std::string&, const std::string&,
+ const KeyCompareBasePtr&,
const std::vector<MapIndexBasePtr>&, bool);
virtual ~MapHelperI();
@@ -106,6 +117,12 @@ public:
virtual IteratorHelper*
find(const Key&, bool) const;
+ virtual IteratorHelper*
+ lowerBound(const Key&, bool) const;
+
+ virtual IteratorHelper*
+ upperBound(const Key&, bool) const;
+
virtual void
put(const Key&, const Value&);
diff --git a/cpp/src/Freeze/SharedDb.cpp b/cpp/src/Freeze/SharedDb.cpp
index 4e1c490f585..8cfd9feb1a3 100644
--- a/cpp/src/Freeze/SharedDb.cpp
+++ b/cpp/src/Freeze/SharedDb.cpp
@@ -44,6 +44,20 @@ checkTypes(const SharedDb& sharedDb, const string& key, const string& value)
}
}
+extern "C"
+{
+static int customCompare(DB* db, const DBT* dbt1, const DBT* dbt2)
+{
+ SharedDb* me = static_cast<SharedDb*>(db->app_private);
+ Byte* first = static_cast<Byte*>(dbt1->data);
+ Key k1(first, first + dbt1->size);
+ first = static_cast<Byte*>(dbt2->data);
+ Key k2(first, first + dbt2->size);
+
+ return me->getKeyCompare()->compare(k1, k2);
+}
+}
+
Freeze::SharedDb::SharedDbMap* Freeze::SharedDb::sharedDbMap = 0;
const string&
@@ -57,6 +71,7 @@ Freeze::SharedDb::get(const ConnectionIPtr& connection,
const string& dbName,
const string& key,
const string& value,
+ const KeyCompareBasePtr& keyCompare,
const vector<MapIndexBasePtr>& indices,
bool createDb)
{
@@ -96,7 +111,8 @@ Freeze::SharedDb::get(const ConnectionIPtr& connection,
//
// MapKey not found, let's create and open a new Db
//
- auto_ptr<SharedDb> result(new SharedDb(mapKey, key, value, connection, indices, createDb));
+ auto_ptr<SharedDb> result(new SharedDb(mapKey, key, value, connection,
+ keyCompare, indices, createDb));
//
// Insert it into the map
@@ -221,10 +237,12 @@ Freeze::SharedDb::SharedDb(const MapKey& mapKey,
const string& key,
const string& value,
const ConnectionIPtr& connection,
+ const KeyCompareBasePtr& keyCompare,
const vector<MapIndexBasePtr>& indices,
bool createDb) :
Db(connection->dbEnv()->getEnv(), 0),
_mapKey(mapKey),
+ _keyCompare(keyCompare),
_refCount(0),
_trace(connection->trace())
{
@@ -234,7 +252,8 @@ Freeze::SharedDb::SharedDb(const MapKey& mapKey,
out << "opening Db \"" << _mapKey.dbName << "\"";
}
- ConnectionPtr catalogConnection = createConnection(_mapKey.communicator, connection->dbEnv()->getEnvName());
+ ConnectionPtr catalogConnection =
+ createConnection(_mapKey.communicator, connection->dbEnv()->getEnvName());
Catalog catalog(catalogConnection, _catalogName);
Catalog::iterator ci = catalog.find(_mapKey.dbName);
@@ -258,6 +277,12 @@ Freeze::SharedDb::SharedDb(const MapKey& mapKey,
_value = value;
}
+ set_app_private(this);
+ if(_keyCompare->compareEnabled())
+ {
+ set_bt_compare(&customCompare);
+ }
+
try
{
TransactionPtr tx = catalogConnection->beginTransaction();
diff --git a/cpp/src/Freeze/SharedDb.h b/cpp/src/Freeze/SharedDb.h
index c51dcb45983..dd881f74725 100644
--- a/cpp/src/Freeze/SharedDb.h
+++ b/cpp/src/Freeze/SharedDb.h
@@ -34,7 +34,10 @@ public:
~MapIndexI();
- IteratorHelper* untypedFind(const Key&, bool, const MapHelperI&) const;
+ IteratorHelper* untypedFind(const Key&, bool, const MapHelperI&, bool) const;
+ IteratorHelper* untypedLowerBound(const Key&, bool, const MapHelperI&) const;
+ IteratorHelper* untypedUpperBound(const Key&, bool, const MapHelperI&) const;
+
int untypedCount(const Key&, const ConnectionIPtr&) const;
int
@@ -50,6 +53,11 @@ public:
return _db.get();
}
+ const MapIndexBasePtr& getKeyCompare() const
+ {
+ return _index;
+ }
+
private:
const MapIndexBasePtr _index;
@@ -66,6 +74,7 @@ public:
static SharedDbPtr get(const ConnectionIPtr&, const std::string&,
const std::string&, const std::string&,
+ const KeyCompareBasePtr&,
const std::vector<MapIndexBasePtr>&, bool);
static SharedDbPtr openCatalog(SharedDbEnv&);
@@ -84,6 +93,9 @@ public:
const std::string&
value() const;
+ const KeyCompareBasePtr&
+ getKeyCompare() const;
+
#ifdef __HP_aCC
virtual int
@@ -110,7 +122,8 @@ private:
typedef std::map<MapKey, Freeze::SharedDb*> SharedDbMap;
SharedDb(const MapKey&, const std::string&, const std::string&,
- const ConnectionIPtr&, const std::vector<MapIndexBasePtr>&, bool);
+ const ConnectionIPtr&, const KeyCompareBasePtr&,
+ const std::vector<MapIndexBasePtr>&, bool);
SharedDb(const MapKey&, DbEnv*);
@@ -123,6 +136,7 @@ private:
int _refCount;
Ice::Int _trace;
+ KeyCompareBasePtr _keyCompare;
IndexMap _indices;
static SharedDbMap* sharedDbMap;
@@ -146,6 +160,11 @@ SharedDb::value() const
return _value;
}
+inline const Freeze::KeyCompareBasePtr&
+SharedDb::getKeyCompare() const
+{
+ return _keyCompare;
+}
inline bool
SharedDb::MapKey::operator<(const MapKey& rhs) const
diff --git a/cpp/src/slice2freeze/Main.cpp b/cpp/src/slice2freeze/Main.cpp
index 10d308cb595..6900e89d959 100644
--- a/cpp/src/slice2freeze/Main.cpp
+++ b/cpp/src/slice2freeze/Main.cpp
@@ -16,10 +16,14 @@ using namespace std;
using namespace IceUtil;
using namespace Slice;
+static string ICE_ENCODING_COMPARE = "Freeze::IceEncodingCompare";
+
struct DictIndex
{
string member;
bool caseSensitive;
+ bool sort;
+ string userCompare;
bool operator==(const DictIndex& rhs) const
{
@@ -32,6 +36,8 @@ struct Dict
string name;
string key;
string value;
+ bool sort;
+ string userCompare;
vector<DictIndex> indices;
};
@@ -63,10 +69,15 @@ usage(const char* n)
"-E Print preprocessor output on stdout.\n"
"--include-dir DIR Use DIR as the header include directory in source files.\n"
"--dll-export SYMBOL Use SYMBOL for DLL exports.\n"
- "--dict NAME,KEY,VALUE Create a Freeze dictionary with the name NAME,\n"
+ "--dict NAME,KEY,VALUE[,sort[,COMPARE]]\n"
+ " Create a Freeze dictionary with the name NAME,\n"
" using KEY as key, and VALUE as value. This\n"
" option may be specified multiple times for\n"
" different names. NAME may be a scoped name.\n"
+ " By default, keys are sorted using their binary\n"
+ " Ice-encoding representation. Use 'sort' to sort\n"
+ " with the COMPARE functor class. COMPARE's default\n"
+ " value is std::less<KEY>\n"
"--index NAME,TYPE,MEMBER[,{case-sensitive|case-insensitive}]\n"
" Create a Freeze evictor index with the name\n"
" NAME for member MEMBER of class TYPE. This\n"
@@ -74,7 +85,8 @@ usage(const char* n)
" different names. NAME may be a scoped name.\n"
" When member is a string, the case can be\n"
" sensitive or insensitive (default is sensitive).\n"
- "--dict-index DICT[,MEMBER][,{case-sensitive|case-insensitive}] \n"
+ "--dict-index DICT[,MEMBER][,{case-sensitive|case-insensitive}]\n"
+ " [,sort[,COMPARE]]\n"
" Add an index to dictionary DICT. If MEMBER is \n"
" specified, then DICT's VALUE must be a class or\n"
" a struct, and MEMBER must designate a member of\n"
@@ -82,6 +94,10 @@ usage(const char* n)
" indexing. When the secondary key is a string, \n"
" the case can be sensitive or insensitive (default\n"
" is sensitive).\n"
+ " By default, keys are sorted using their binary\n"
+ " Ice-encoding representation. Use 'sort' to sort\n"
+ " with the COMPARE functor class. COMPARE's default\n"
+ " value is std::less<secondary key type>\n."
"--output-dir DIR Create files in the directory DIR.\n"
"-d, --debug Print debug messages.\n"
"--ice Permit `Ice' prefix (for building Ice source code only)\n"
@@ -117,7 +133,8 @@ printFreezeTypes(Output& out, const vector<Dict>& dicts, const vector<Index>& in
out << "\n// Freeze types in this file:";
for(vector<Dict>::const_iterator p = dicts.begin(); p != dicts.end(); ++p)
{
- out << "\n// name=\"" << p->name << "\", key=\"" << p->key << "\", value=\"" << p->value << "\"";
+ out << "\n// name=\"" << p->name << "\", key=\""
+ << p->key << "\", value=\"" << p->value << "\"";
}
for(vector<Index>::const_iterator q = indices.begin(); q != indices.end(); ++q)
@@ -132,6 +149,27 @@ printFreezeTypes(Output& out, const vector<Dict>& dicts, const vector<Index>& in
out << '\n';
}
+template<class T>
+inline string
+getCompare(const T& t, const string& keyType)
+{
+ if(t.sort)
+ {
+ if(t.userCompare == "")
+ {
+ return "std::less<" + keyType + ">";
+ }
+ else
+ {
+ return t.userCompare;
+ }
+ }
+ else
+ {
+ return ICE_ENCODING_COMPARE;
+ }
+}
+
void
writeCodecH(const TypePtr& type, const string& name, const string& freezeType, Output& H, const string& dllExport)
{
@@ -142,9 +180,9 @@ writeCodecH(const TypePtr& type, const string& name, const string& freezeType, O
H << sp;
H.inc();
H << nl << "static void write(" << inputTypeToString(type)
- << ", Freeze::" << freezeType << "& bytes, const ::Ice::CommunicatorPtr& communicator);";
- H << nl << "static void read(" << typeToString(type) << "&, const Freeze::" << freezeType << "& bytes, "
- << "const ::Ice::CommunicatorPtr& communicator);";
+ << ", Freeze::" << freezeType << "&, const ::Ice::CommunicatorPtr&);";
+ H << nl << "static void read(" << typeToString(type) << "&, const Freeze::" << freezeType << "&, "
+ << "const ::Ice::CommunicatorPtr&);";
H << nl << "static const std::string& typeId();";
H << eb << ';';
}
@@ -231,11 +269,16 @@ writeDictWithIndicesH(const string& name, const Dict& dict,
const TypePtr& keyType, const TypePtr& valueType,
Output& H, const string& dllExport)
{
+ string compare = getCompare(dict, typeToString(keyType));
- string templateParams = string("< ") + typeToString(keyType) + ", "
+ string templateParams = string("<") + typeToString(keyType) + ", "
+ typeToString(valueType) + ", " + name + "KeyCodec, "
- + name + "ValueCodec>";
-
+ + name + "ValueCodec, " + compare + " >";
+
+ string keyCompareParams =
+ string("< ") + typeToString(keyType) + ", "
+ + name + "KeyCodec, " + compare + " >";
+
vector<string> capitalizedMembers;
size_t i;
for(i = 0; i < dict.indices.size(); ++i)
@@ -264,6 +307,7 @@ writeDictWithIndicesH(const string& name, const Dict& dict,
//
// Typedefs
//
+ /*
H << nl << "typedef std::pair<const " << typeToString(keyType)
<< ", const" << typeToString(valueType) << "> value_type;";
@@ -271,27 +315,44 @@ writeDictWithIndicesH(const string& name, const Dict& dict,
H << nl << "typedef Freeze::ConstIterator" << templateParams << " const_iterator;";
H << nl << "typedef size_t size_type;";
H << nl << "typedef ptrdiff_t difference_type;";
-
+ */
+
//
// Nested index classes
//
for(i = 0; i < capitalizedMembers.size(); ++i)
{
- H << sp << nl << "class " << dllExport << capitalizedMembers[i] << "Index"
- << " : public Freeze::MapIndexBase";
+ string className = capitalizedMembers[i] + "Index";
+
+ string indexCompare = getCompare(dict.indices[i], typeToString(indexTypes[i]));
+
+ string indexCompareParams =
+ string("< ") + typeToString(indexTypes[i]) + ", "
+ + className + ", " + indexCompare + " >";
+
+ H << sp << nl << "class " << dllExport << className
+ << " : public Freeze::MapIndex" << indexCompareParams;
H << sb;
H.dec();
H << sp << nl << "public:";
H << sp;
H.inc();
- H << nl << capitalizedMembers[i] << "Index(const std::string&);";
+ H << nl << capitalizedMembers[i] << "Index(const std::string&, const "
+ << indexCompare << "& = " << indexCompare << "());";
H << sp;
- H << nl << "static void writeIndex(" << inputTypeToString(indexTypes[i])
+
+ //
+ // Codec
+ //
+ H << nl << "static void write(" << inputTypeToString(indexTypes[i])
<< ", Freeze::Key&, const Ice::CommunicatorPtr&);";
+ H << nl << "static void read("
+ << typeToString(indexTypes[i])
+ << "&, const Freeze::Key&, const ::Ice::CommunicatorPtr&);";
H.dec();
H << sp << nl << "protected:";
@@ -307,15 +368,20 @@ writeDictWithIndicesH(const string& name, const Dict& dict,
// Constructors
//
H << sp;
- H << nl << name << "(const Freeze::ConnectionPtr&, const std::string&, bool = true);";
+ H << nl << name << "(const Freeze::ConnectionPtr&, const std::string&, "
+ << "bool = true, const " << compare << "& = " << compare << "());";
H << sp;
H << nl << "template <class _InputIterator>"
- << nl << name << "(const Freeze::ConnectionPtr& __connection, const std::string& __dbName, bool __createDb, "
- << "_InputIterator __first, _InputIterator __last)";
+ << nl << name << "(const Freeze::ConnectionPtr& __connection, "
+ << "const std::string& __dbName, bool __createDb, "
+ << "_InputIterator __first, _InputIterator __last, "
+ << "const " << compare << "& __compare = " << compare << "())";
H.inc();
H << nl << ": Freeze::Map" << templateParams <<"(__connection->getCommunicator())";
H.dec();
H << sb;
+ H << nl << "Freeze::KeyCompareBasePtr __keyCompare = "
+ << "new Freeze::KeyCompare" << keyCompareParams << "(__compare, _communicator);";
H << nl << "std::vector<Freeze::MapIndexBasePtr> __indices;";
for(i = 0; i < capitalizedMembers.size(); ++i)
{
@@ -330,7 +396,7 @@ writeDictWithIndicesH(const string& name, const Dict& dict,
}
H << nl << "this->_helper.reset(Freeze::MapHelper::create(__connection, __dbName, "
<< name + "KeyCodec::typeId(), "
- << name + "ValueCodec::typeId(), __indices, __createDb));";
+ << name + "ValueCodec::typeId(), __keyCompare, __indices, __createDb));";
H << nl << "while(__first != __last)";
H << sb;
H << nl << "put(*__first);";
@@ -339,16 +405,32 @@ writeDictWithIndicesH(const string& name, const Dict& dict,
H << eb;
//
- // Find and count functions
+ // Find, lowerBound, upperBound, equalRange and count functions
//
for(i = 0; i < capitalizedMembers.size(); ++i)
{
H << sp;
H << nl << "iterator findBy" << capitalizedMembers[i]
- << "(" << inputTypeToString(indexTypes[i]) << ");";
+ << "(" << inputTypeToString(indexTypes[i]) << ", bool = true);";
H << nl << "const_iterator findBy" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << ", bool = true) const;";
+
+ H << nl << "iterator lowerBoundFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << ");";
+ H << nl << "const_iterator lowerBoundFor" << capitalizedMembers[i]
<< "(" << inputTypeToString(indexTypes[i]) << ") const;";
+ H << nl << "iterator upperBoundFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << ");";
+ H << nl << "const_iterator upperBoundFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << ") const;";
+
+ H << nl << "std::pair<iterator, iterator> equalRangeFor"
+ << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i]) << ");";
+
+ H << nl << "std::pair<const_iterator, const_iterator> equalRangeFor"
+ << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i]) << ") const;";
+
string countFunction = dict.indices[i].member.empty() ? "valueCount"
: dict.indices[i].member + "Count";
@@ -364,10 +446,16 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
const vector<TypePtr> indexTypes,
const TypePtr& keyType, const TypePtr& valueType,
Output& C)
-{
- string templateParams = string("< ") + typeToString(keyType) + ", "
+{
+ string compare = getCompare(dict, typeToString(keyType));
+
+ string templateParams = string("<") + typeToString(keyType) + ", "
+ typeToString(valueType) + ", " + name + "KeyCodec, "
- + name + "ValueCodec>";
+ + name + "ValueCodec, " + compare + " >";
+
+ string keyCompareParams =
+ string("< ") + typeToString(keyType) + ", "
+ + name + "KeyCodec, " + compare + " >";
vector<string> capitalizedMembers;
size_t i;
@@ -390,16 +478,24 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
//
// Nested index classes
//
-
for(i = 0; i < capitalizedMembers.size(); ++i)
{
string className = capitalizedMembers[i] + "Index";
+ string indexCompare =
+ getCompare(dict.indices[i], typeToString(indexTypes[i]));
+
+ string indexCompareParams =
+ string("< ") + typeToString(indexTypes[i]) + ", "
+ + className + ", " + indexCompare + " >";
+
C << sp << nl << absolute << "::" << className << "::" << className
- << "(const std::string& __name)";
+ << "(const std::string& __name, "
+ << "const " << indexCompare << "& __compare)";
C.inc();
- C << nl << ": Freeze::MapIndexBase(__name)";
+ C << nl << ": Freeze::MapIndex"
+ << indexCompareParams << "(__name, __compare)";
C.dec();
C << sb;
C << eb;
@@ -436,13 +532,13 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
param += "." + dict.indices[i].member;
}
}
- C << nl << "writeIndex(" << param << ", __k, _communicator);";
+ C << nl << "write(" << param << ", __k, _communicator);";
}
C << eb;
C << sp << nl << "void"
<< nl << absolute << "::" << className << "::"
- << "writeIndex(" << inputTypeToString(indexTypes[i])
+ << "write(" << inputTypeToString(indexTypes[i])
<< " __index, Freeze::Key& __bytes, const Ice::CommunicatorPtr& __communicator)";
C << sb;
@@ -452,6 +548,8 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
}
else
{
+ assert(!indexTypes[i]->usesClasses());
+
C << nl << "IceInternal::InstancePtr __instance = IceInternal::getInstance(__communicator);";
C << nl << "IceInternal::BasicStream __stream(__instance.get());";
@@ -468,27 +566,46 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
}
writeMarshalUnmarshalCode(C, indexTypes[i], valueS, true, "__stream", false);
- if(indexTypes[i]->usesClasses())
- {
- C << nl << "__stream.writePendingObjects();";
- }
C << nl << "::std::vector<Ice::Byte>(__stream.b.begin(), __stream.b.end()).swap(__bytes);";
}
C << eb;
- }
+ C << sp << nl << "void"
+ << nl << absolute << "::" << className << "::"
+ << "read(" << typeToString(indexTypes[i])
+ << "& __index, const Freeze::Key& __bytes, const Ice::CommunicatorPtr& __communicator)";
+ C << sb;
+
+ if(optimize)
+ {
+ C << nl << absolute << "ValueCodec::read(__index, __bytes, __communicator);";
+ }
+ else
+ {
+ C << nl << "IceInternal::InstancePtr __instance = IceInternal::getInstance(__communicator);";
+ C << nl << "IceInternal::BasicStream __stream(__instance.get());";
+
+ C << nl << "__stream.b.resize(__bytes.size());";
+ C << nl << "::memcpy(&__stream.b[0], &__bytes[0], __bytes.size());";
+ C << nl << "__stream.i = __stream.b.begin();";
+ writeMarshalUnmarshalCode(C, indexTypes[i], "__index", false, "__stream", false);
+ }
+ C << eb;
+ }
//
// Constructor
//
-
C << sp << nl << absolute << "::" << name
- << "(const Freeze::ConnectionPtr& __connection, const std::string& __dbName , bool __createDb)";
+ << "(const Freeze::ConnectionPtr& __connection, const std::string& __dbName ,"
+ << "bool __createDb, const " << compare << "& __compare)";
C.inc();
C << nl << ": Freeze::Map" << templateParams <<"(__connection->getCommunicator())";
C.dec();
C << sb;
+ C << nl << "Freeze::KeyCompareBasePtr __keyCompare = "
+ << "new Freeze::KeyCompare" << keyCompareParams << "(__compare, _communicator);";
C << nl << "std::vector<Freeze::MapIndexBasePtr> __indices;";
for(i = 0; i < capitalizedMembers.size(); ++i)
{
@@ -503,7 +620,7 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
}
C << nl << "_helper.reset(Freeze::MapHelper::create(__connection, __dbName, "
<< absolute + "KeyCodec::typeId(), "
- << absolute + "ValueCodec::typeId(), __indices, __createDb));";
+ << absolute + "ValueCodec::typeId(), __keyCompare, __indices, __createDb));";
C << eb;
//
@@ -522,22 +639,80 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
C << sp << nl << absolute << "::iterator"
<< nl << absolute << "::" << "findBy" << capitalizedMembers[i]
- << "(" << inputTypeToString(indexTypes[i]) << " __index)";
+ << "(" << inputTypeToString(indexTypes[i]) << " __index, bool __onlyDups)";
C << sb;
C << nl << "Freeze::Key __bytes;";
- C << nl << indexClassName << "::" << "writeIndex(__index, __bytes, _communicator);";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
C << nl << "return iterator(_helper->index(" << indexName
- << ")->untypedFind(__bytes, false), _communicator);";
+ << ")->untypedFind(__bytes, false, __onlyDups), _communicator);";
C << eb;
C << sp << nl << absolute << "::const_iterator"
<< nl << absolute << "::" << "findBy" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << " __index, bool __onlyDups) const";
+ C << sb;
+ C << nl << "Freeze::Key __bytes;";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
+ C << nl << "return const_iterator(_helper->index(" << indexName
+ << ")->untypedFind(__bytes, true, __onlyDups), _communicator);";
+ C << eb;
+
+ C << sp << nl << absolute << "::iterator"
+ << nl << absolute << "::" << "lowerBoundFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << " __index)";
+ C << sb;
+ C << nl << "Freeze::Key __bytes;";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
+ C << nl << "return iterator(_helper->index(" << indexName
+ << ")->untypedLowerBound(__bytes, false), _communicator);";
+ C << eb;
+
+ C << sp << nl << absolute << "::const_iterator"
+ << nl << absolute << "::" << "lowerBoundFor" << capitalizedMembers[i]
<< "(" << inputTypeToString(indexTypes[i]) << " __index) const";
C << sb;
C << nl << "Freeze::Key __bytes;";
- C << nl << indexClassName << "::" << "writeIndex(__index, __bytes, _communicator);";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
C << nl << "return const_iterator(_helper->index(" << indexName
- << ")->untypedFind(__bytes, true), _communicator);";
+ << ")->untypedLowerBound(__bytes, true), _communicator);";
+ C << eb;
+
+ C << sp << nl << absolute << "::iterator"
+ << nl << absolute << "::" << "upperBoundFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << " __index)";
+ C << sb;
+ C << nl << "Freeze::Key __bytes;";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
+ C << nl << "return iterator(_helper->index(" << indexName
+ << ")->untypedUpperBound(__bytes, false), _communicator);";
+ C << eb;
+
+ C << sp << nl << absolute << "::const_iterator"
+ << nl << absolute << "::" << "upperBoundFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << " __index) const";
+ C << sb;
+ C << nl << "Freeze::Key __bytes;";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
+ C << nl << "return const_iterator(_helper->index(" << indexName
+ << ")->untypedUpperBound(__bytes, true), _communicator);";
+ C << eb;
+
+ C << sp << nl << "std::pair<" << absolute << "::iterator, "
+ << absolute << "::iterator>"
+ << nl << absolute << "::" << "equalRangeFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << " __index)";
+ C << sb;
+ C << nl << "return std::make_pair(lowerBoundFor" << capitalizedMembers[i]
+ << "(__index), upperBoundFor" << capitalizedMembers[i] << "(__index));";
+ C << eb;
+
+ C << sp << nl << "std::pair<" << absolute << "::const_iterator, "
+ << absolute << "::const_iterator>"
+ << nl << absolute << "::" << "equalRangeFor" << capitalizedMembers[i]
+ << "(" << inputTypeToString(indexTypes[i]) << " __index) const";
+ C << sb;
+ C << nl << "return std::make_pair(lowerBoundFor" << capitalizedMembers[i]
+ << "(__index), upperBoundFor" << capitalizedMembers[i] << "(__index));";
C << eb;
string countFunction = dict.indices[i].member.empty() ? "valueCount"
@@ -548,7 +723,7 @@ writeDictWithIndicesC(const string& name, const string& absolute, const Dict& di
<< "(" << inputTypeToString(indexTypes[i]) << " __index) const";
C << sb;
C << nl << "Freeze::Key __bytes;";
- C << nl << indexClassName << "::" << "writeIndex(__index, __bytes, _communicator);";
+ C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator);";
C << nl << "return _helper->index(" << indexName
<< ")->untypedCount(__bytes);";
C << eb;
@@ -616,8 +791,12 @@ writeDict(const string& n, UnitPtr& u, const Dict& dict, Output& H, Output& C, c
if(dict.indices.size() == 0)
{
- H << sp << nl << "typedef Freeze::Map< " << typeToString(keyType) << ", " << typeToString(valueType) << ", "
- << name << "KeyCodec, " << name << "ValueCodec> " << name << ";";
+ string compare = getCompare(dict, typeToString(keyType));
+
+ H << sp << nl << "typedef Freeze::Map< " << typeToString(keyType)
+ << ", " << typeToString(valueType) << ", "
+ << name << "KeyCodec, " << name << "ValueCodec, " << compare
+ << " > " << name << ";";
}
else
{
@@ -691,7 +870,8 @@ writeDict(const string& n, UnitPtr& u, const Dict& dict, Output& H, Output& C, c
if(dataMember == 0)
{
- cerr << n << ": The value of `" << dict.name << "' has no data member named `" << index.member << "'" << endl;
+ cerr << n << ": The value of `" << dict.name
+ << "' has no data member named `" << index.member << "'" << endl;
return false;
}
@@ -956,9 +1136,6 @@ writeIndex(const string& n, UnitPtr& u, const Index& index, Output& H, Output& C
return true;
}
-
-
-
int
main(int argc, char* argv[])
{
@@ -1080,7 +1257,44 @@ main(int argc, char* argv[])
dict.key = s.substr(0, pos);
s.erase(0, pos + 1);
}
- dict.value = s;
+ pos = s.find(',');
+ if(pos == string::npos)
+ {
+ dict.value = s;
+ dict.sort = false;
+ }
+ else
+ {
+ dict.value = s.substr(0, pos);
+ s.erase(0, pos + 1);
+
+ pos = s.find(',');
+ if(pos == string::npos)
+ {
+ if(s != "sort")
+ {
+ cerr << argv[0] << ": " << *i
+ << ": nothing or ',sort' expected after value-type" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ dict.sort = true;
+ }
+ else
+ {
+ string sort = s.substr(0, pos);
+ s.erase(0, pos + 1);
+ if(sort != "sort")
+ {
+ cerr << argv[0] << ": " << *i
+ << ": nothing or ',sort' expected after value-type" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ dict.sort = true;
+ dict.userCompare = s;
+ }
+ }
if(dict.name.empty())
{
@@ -1185,39 +1399,96 @@ main(int argc, char* argv[])
string dictName;
DictIndex index;
- string::size_type pos;
-
- string caseString = "case-sensitive";
- pos = s.find(',');
- if(pos != string::npos)
+ index.sort = false;
+ index.caseSensitive = true;
+
+ string::size_type pos = s.find(',');
+ if(pos == string::npos)
+ {
+ dictName = s;
+ }
+ else
{
dictName = s.substr(0, pos);
s.erase(0, pos + 1);
- pos = s.find(',');
- if(pos != string::npos)
+ bool done = false;
+ while(!done)
{
- index.member = s.substr(0, pos);
- s.erase(0, pos + 1);
- caseString = s;
- }
- else
- {
- if(s == "case-sensitive" || s == "case-insensitive")
+ pos = s.find(',');
+ if(pos == string::npos)
{
- caseString = s;
+ if(s == "sort")
+ {
+ index.sort = true;
+ }
+ else if(s == "case-sensitive")
+ {
+ index.caseSensitive = true;
+ }
+ else if(s == "case-insensitive")
+ {
+ index.caseSensitive = false;
+ }
+ else if(index.member.empty())
+ {
+ if(s == "\\sort")
+ {
+ index.member = "sort";
+ }
+ else
+ {
+ index.member = s;
+ }
+ }
+ else
+ {
+ cerr << argv[0] << ": " << *i << ": syntax error" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ done = true;
}
else
{
- index.member = s;
+ string subs = s.substr(0, pos);
+ s.erase(0, pos + 1);
+
+ if(subs == "sort")
+ {
+ index.sort = true;
+ index.userCompare = s;
+ done = true;
+ }
+ else if(subs == "case-sensitive")
+ {
+ index.caseSensitive = true;
+ }
+ else if(subs == "case-insensitive")
+ {
+ index.caseSensitive = false;
+ }
+ else if(index.member.empty())
+ {
+ if(subs == "\\sort")
+ {
+ index.member = "sort";
+ }
+ else
+ {
+ index.member = subs;
+ }
+ }
+ else
+ {
+ cerr << argv[0] << ": " << *i << ": syntax error" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
}
}
}
- else
- {
- dictName = s;
- }
-
+
if(dictName.empty())
{
cerr << argv[0] << ": " << *i << ": no dictionary specified" << endl;
@@ -1225,14 +1496,6 @@ main(int argc, char* argv[])
return EXIT_FAILURE;
}
- if(caseString != "case-sensitive" && caseString != "case-insensitive")
- {
- cerr << argv[0] << ": " << *i << ": the case can be `case-sensitive' or `case-insensitive'" << endl;
- usage(argv[0]);
- return EXIT_FAILURE;
- }
- index.caseSensitive = (caseString == "case-sensitive");
-
bool found = false;
for(vector<Dict>::iterator p = dicts.begin(); p != dicts.end(); ++p)
{
@@ -1240,7 +1503,8 @@ main(int argc, char* argv[])
{
if(find(p->indices.begin(), p->indices.end(), index) != p->indices.end())
{
- cerr << argv[0] << ": --dict-index " << *i << ": this dict-index is defined twice" << endl;
+ cerr << argv[0] << ": --dict-index " << *i
+ << ": this dict-index is defined twice" << endl;
return EXIT_FAILURE;
}
p->indices.push_back(index);