diff options
author | Bernard Normier <bernard@zeroc.com> | 2005-11-08 00:13:52 +0000 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2005-11-08 00:13:52 +0000 |
commit | 20c342c1c5f35fbe60565dee7fb81ca2baf04e5b (patch) | |
tree | 199faf2102026478de9a1e55f6fff271591e7b98 /cpp/src | |
parent | fixed bi-dir/shutdown deadlock (diff) | |
download | ice-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.cpp | 287 | ||||
-rw-r--r-- | cpp/src/Freeze/MapI.h | 19 | ||||
-rw-r--r-- | cpp/src/Freeze/SharedDb.cpp | 29 | ||||
-rw-r--r-- | cpp/src/Freeze/SharedDb.h | 23 | ||||
-rw-r--r-- | cpp/src/slice2freeze/Main.cpp | 422 |
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); |