summaryrefslogtreecommitdiff
path: root/cpp
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
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')
-rw-r--r--cpp/CHANGES34
-rw-r--r--cpp/include/Freeze/Map.h305
-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
-rw-r--r--cpp/test/Freeze/dbmap/Client.cpp110
-rw-r--r--cpp/test/Freeze/dbmap/Makefile8
-rw-r--r--cpp/test/Freeze/dbmap/dbmap.dsp24
10 files changed, 1113 insertions, 148 deletions
diff --git a/cpp/CHANGES b/cpp/CHANGES
index 2f0e00ef88a..7e2a954f5c5 100644
--- a/cpp/CHANGES
+++ b/cpp/CHANGES
@@ -1,18 +1,38 @@
Changes since version 2.1.2
---------------------------
+- Added custom-compare to Freeze Maps:
+ you can now provide your own compare functors for keys and indices. See
+ the slice2freeze usage for the new options. The default compare uses
+ compares binary strings encoded using the Ice encoding (like in previous
+ releases).
+ Map have 4 new functions:
+ - lower_bound (const and non-const)
+ - upper_bound (const and non-const)
+ In addition, the implementation of equal_range is now correct.
+
+ Generated index classes have 6 new functions:
+ - lowerBoundFor<name> (const and non-const)
+ - upperBoundFor<name> (const and non-const)
+ - equalRangeFor<name> (const and non-const)
+ The findBy<name> also takes a new bool parameter, "onlyDups"; its default
+ value is true for compatibility with previous releases. When onlyDups is
+ true, findBy<name> returns only the elements that match the given index
+ value; when false, the iterator returns first these elements and then
+ lets you iterate over the remainder of the database (according to the order
+ defined by the index).
+
- Fixed a deadlock during shutdown that could happen with
bi-directional connections.
- Removed ice_default() method from proxies.
-- Added downgrade() to IceUtil::RWRecMutex and fixed a bug in
- upgrade(): previously, upgrade() was equivalent to calling unlock()
- followed by writeLock(), which could allow a thread to acquire a
- write lock while another thread was in the middle an
- upgrade. upgrade() is now atomic, so whatever state is protected by
- a read lock is guaranteed to be still unchanged when upgrade()
- completes.
+- Added downgrade() to IceUtil::RWRecMutex and fixed a bug in upgrade():
+ previously, upgrade() was equivalent to calling unlock() followed
+ by writeLock(), which could allow a thread to acquire a write lock while
+ another thread was in the middle an upgrade. upgrade() is now atomic, so
+ whatever state is protected by a read lock is guaranteed to be still
+ unchanged when upgrade() completes.
- Connection::close(false) (i.e., graceful connection shutdown) now
waits until all outstanding requests have completed.
diff --git a/cpp/include/Freeze/Map.h b/cpp/include/Freeze/Map.h
index a489af84fb8..365e2a03af2 100644
--- a/cpp/include/Freeze/Map.h
+++ b/cpp/include/Freeze/Map.h
@@ -32,7 +32,21 @@ class MapHelperI;
class IteratorHelperI;
class SharedDb;
-class FREEZE_API MapIndexBase : public IceUtil::Shared
+class FREEZE_API KeyCompareBase : public IceUtil::Shared
+{
+public:
+ KeyCompareBase(bool);
+
+ bool compareEnabled() const;
+
+ virtual int compare(const Key&, const Key&) = 0;
+
+private:
+ const bool _enabled;
+};
+typedef IceUtil::Handle<KeyCompareBase> KeyCompareBasePtr;
+
+class FREEZE_API MapIndexBase : public KeyCompareBase
{
public:
@@ -40,7 +54,10 @@ public:
const std::string& name() const;
- IteratorHelper* untypedFind(const Key&, bool) const;
+ IteratorHelper* untypedFind(const Key&, bool, bool) const;
+ IteratorHelper* untypedLowerBound(const Key&, bool) const;
+ IteratorHelper* untypedUpperBound(const Key&, bool) const;
+
int untypedCount(const Key&) const;
//
@@ -50,7 +67,7 @@ public:
protected:
- MapIndexBase(const std::string&);
+ MapIndexBase(const std::string&, bool);
Ice::CommunicatorPtr _communicator;
@@ -63,11 +80,10 @@ private:
std::string _name;
MapIndexI* _impl;
const MapHelperI* _map;
+ const KeyCompareBasePtr _keyCompare;
};
-
typedef IceUtil::Handle<MapIndexBase> MapIndexBasePtr;
-
class FREEZE_API MapHelper
{
public:
@@ -77,6 +93,7 @@ public:
const std::string& dbName,
const std::string& key,
const std::string& value,
+ const KeyCompareBasePtr&,
const std::vector<MapIndexBasePtr>&,
bool createDb);
@@ -85,6 +102,12 @@ public:
virtual IteratorHelper*
find(const Key&, bool) const = 0;
+ virtual IteratorHelper*
+ lowerBound(const Key&, bool) const = 0;
+
+ virtual IteratorHelper*
+ upperBound(const Key&, bool) const = 0;
+
virtual void
put(const Key&, const Value&) = 0;
@@ -144,9 +167,11 @@ public:
//
// Forward declaration
//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+template <typename key_type, typename mapped_type,
+ typename KeyCodec, typename ValueCodec, typename Compare>
class Map;
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+template <typename key_type, typename mapped_type,
+ typename KeyCodec, typename ValueCodec, typename Compare>
class ConstIterator;
//
@@ -168,7 +193,8 @@ struct IteratorBase
// TODO: It's possible to implement bidirectional iterators, if
// necessary.
//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+template<typename key_type, typename mapped_type,
+ typename KeyCodec, typename ValueCodec, typename Compare>
class Iterator : public IteratorBase
{
public:
@@ -344,8 +370,10 @@ private:
ValueCodec::read(value, *v, _communicator);
}
- friend class ConstIterator<key_type, mapped_type, KeyCodec, ValueCodec>;
- friend class Map<key_type, mapped_type, KeyCodec, ValueCodec>;
+ friend class ConstIterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>;
+ friend class Map<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>;
std::auto_ptr<IteratorHelper> _helper;
Ice::CommunicatorPtr _communicator;
@@ -367,7 +395,8 @@ private:
//
// See Iterator comments for design notes
//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+template <typename key_type, typename mapped_type,
+ typename KeyCodec, typename ValueCodec, typename Compare>
class ConstIterator : public IteratorBase
{
public:
@@ -413,7 +442,8 @@ public:
// A Iterator can be converted to a ConstIterator (but not
// vice versa) - same for operator=.
//
- ConstIterator(const Iterator<key_type, mapped_type, KeyCodec, ValueCodec>& rhs) :
+ ConstIterator(const Iterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>& rhs) :
_refValid(false)
{
if(rhs._helper.get() != 0)
@@ -445,7 +475,8 @@ public:
//
// Create const_iterator from iterator.
//
- ConstIterator& operator=(const Iterator<key_type, mapped_type, KeyCodec, ValueCodec>& rhs)
+ ConstIterator& operator=(const Iterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>& rhs)
{
if(rhs._helper.get() != 0)
{
@@ -563,7 +594,8 @@ private:
ValueCodec::read(value, *v, _communicator);
}
- friend class Map<key_type, mapped_type, KeyCodec, ValueCodec>;
+ friend class Map<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>;
std::auto_ptr<IteratorHelper> _helper;
Ice::CommunicatorPtr _communicator;
@@ -583,6 +615,161 @@ private:
mutable bool _refValid;
};
+#if defined(_MSC_VER) && (_MSC_VER <= 1300)
+//
+// Without partial template specialization
+//
+struct IceEncodingCompare
+{
+ bool operator()(...)
+ {
+ return false;
+ }
+};
+
+template<typename Compare>
+inline bool
+enableKeyCompare(const Compare&)
+{
+ return true;
+}
+
+template<>
+inline bool
+enableKeyCompare<IceEncodingCompare>(const IceEncodingCompare&)
+{
+ return false;
+}
+# else
+struct IceEncodingCompare {};
+#endif
+
+template<typename key_type, typename KeyCodec, typename Compare>
+class KeyCompare : public KeyCompareBase
+{
+public:
+ KeyCompare(const Compare& compare,
+ const Ice::CommunicatorPtr& communicator) :
+#if defined(_MSC_VER) && (_MSC_VER <= 1300)
+ KeyCompareBase(enableKeyCompare(compare)),
+#else
+ KeyCompareBase(true),
+#endif
+ _compare(compare),
+ _communicator(communicator)
+ {}
+
+ virtual int compare(const Key& dbKey1, const Key& dbKey2)
+ {
+ key_type key1;
+ KeyCodec::read(key1, dbKey1, _communicator);
+ key_type key2;
+ KeyCodec::read(key2, dbKey2, _communicator);
+
+ if(_compare(key1, key2))
+ {
+ return -1;
+ }
+ else if(_compare(key2, key1))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+private:
+ Compare _compare;
+ Ice::CommunicatorPtr _communicator;
+};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1300)
+//
+// Partial template specialization:
+// do nothing for the IceEncodingCompare comparator
+//
+template<typename key_type, typename KeyCodec>
+class KeyCompare<key_type, KeyCodec, IceEncodingCompare> : public KeyCompareBase
+{
+public:
+ KeyCompare(const IceEncodingCompare&, const Ice::CommunicatorPtr&):
+ KeyCompareBase(false)
+ {}
+
+ virtual int compare(const Key& dbKey1, const Key& dbKey2)
+ {
+ assert(0);
+ return 0;
+ }
+};
+#endif
+
+//
+// Need to separate MapIndex template class because _communicator is
+// set later
+//
+template<typename key_type, typename KeyCodec, typename Compare>
+class MapIndex : public MapIndexBase
+{
+public:
+ virtual int compare(const Key& dbKey1, const Key& dbKey2)
+ {
+ key_type key1;
+ KeyCodec::read(key1, dbKey1, _communicator);
+ key_type key2;
+ KeyCodec::read(key2, dbKey2, _communicator);
+
+ if(_compare(key1, key2))
+ {
+ return -1;
+ }
+ else if(_compare(key2, key1))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+protected:
+ MapIndex(const std::string& name, const Compare& compare) :
+#if defined(_MSC_VER) && (_MSC_VER <= 1300)
+ MapIndexBase(name, enableKeyCompare(compare)),
+#else
+ MapIndexBase(name, true),
+#endif
+ _compare(compare)
+ {}
+
+private:
+ Compare _compare;
+};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1300)
+//
+// Partial template specialization:
+// do nothing for the IceEncodingCompare comparator
+//
+template<typename key_type, typename KeyCodec>
+class MapIndex<key_type, KeyCodec, IceEncodingCompare> : public MapIndexBase
+{
+public:
+ virtual int compare(const Key& dbKey1, const Key& dbKey2)
+ {
+ assert(0);
+ return 0;
+ }
+
+protected:
+ MapIndex(const std::string& name, const IceEncodingCompare&):
+ MapIndexBase(name, false)
+ {}
+};
+#endif
+
//
// This is an STL container that matches the requirements of a
// Associated Container - with the restriction that operator[] isn't
@@ -593,7 +780,9 @@ private:
// TODO: If necessary it would be possible to implement reverse and
// bidirectional iterators.
//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+template<typename key_type, typename mapped_type,
+ typename KeyCodec, typename ValueCodec,
+ typename Compare = IceEncodingCompare>
class Map
{
public:
@@ -606,14 +795,15 @@ public:
// hasher, key_equal, key_compare, value_compare
//
- typedef Iterator<key_type, mapped_type, KeyCodec, ValueCodec > iterator;
- typedef ConstIterator<key_type, mapped_type, KeyCodec, ValueCodec > const_iterator;
+ typedef Iterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare> iterator;
+ typedef ConstIterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare> const_iterator;
//
// No definition for reference, const_reference, pointer or
// const_pointer.
//
-
typedef size_t size_type;
typedef ptrdiff_t difference_type;
@@ -627,27 +817,36 @@ public:
// Constructors
//
Map(const Freeze::ConnectionPtr& connection,
- const std::string& dbName,
- bool createDb = true) :
+ const std::string& dbName,
+ bool createDb = true,
+ const Compare& compare = Compare()) :
_communicator(connection->getCommunicator())
- {
+ {
+ KeyCompareBasePtr keyCompare =
+ new KeyCompare<key_type, KeyCodec, Compare>(compare, _communicator);
std::vector<MapIndexBasePtr> indices;
+
_helper.reset(MapHelper::create(connection, dbName,
- KeyCodec::typeId(), ValueCodec::typeId(),
- indices, createDb));
+ KeyCodec::typeId(), ValueCodec::typeId(),
+ keyCompare, indices, createDb));
}
- template <class _InputIterator>
+ template<class _InputIterator>
Map(const Freeze::ConnectionPtr& connection,
const std::string& dbName,
bool createDb,
- _InputIterator first, _InputIterator last) :
+ _InputIterator first, _InputIterator last,
+ const Compare& compare = Compare()) :
_communicator(connection->getCommunicator())
{
+ KeyCompareBasePtr keyCompare =
+ new KeyCompare<key_type, KeyCodec, Compare>(compare, _communicator);
+
std::vector<MapIndexBasePtr> indices;
+
_helper.reset(MapHelper::create(connection, dbName,
KeyCodec::typeId(), ValueCodec::typeId(),
- indices, createDb));
+ keyCompare, indices, createDb));
while(first != last)
{
put(*first);
@@ -916,16 +1115,47 @@ public:
}
+ iterator lower_bound(const key_type& key)
+ {
+ Key k;
+ KeyCodec::write(key, k, _communicator);
+
+ return iterator(_helper->lowerBound(k, false), _communicator);
+ }
+
+ const_iterator lower_bound(const key_type& key) const
+ {
+ Key k;
+ KeyCodec::write(key, k, _communicator);
+
+ return iterator(_helper->lowerBound(k, true), _communicator);
+ }
+
+ iterator upper_bound(const key_type& key)
+ {
+ Key k;
+ KeyCodec::write(key, k, _communicator);
+
+ return iterator(_helper->upperBound(k, false), _communicator);
+ }
+
+ const_iterator upper_bound(const key_type& key) const
+ {
+ Key k;
+ KeyCodec::write(key, k, _communicator);
+
+ return iterator(_helper->upperBound(k, true), _communicator);
+ }
+
std::pair<iterator, iterator> equal_range(const key_type& key)
{
- iterator p = find(key);
- return std::pair<iterator,iterator>(p,p);
+ return std::make_pair(lower_bound(key), upper_bound(key));
}
- std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
+ std::pair<const_iterator, const_iterator>
+ equal_range(const key_type& key) const
{
- const_iterator p = find(key);
- return std::pair<const_iterator,const_iterator>(p,p);
+ return std::make_pair(lower_bound(key), upper_bound(key));
}
const Ice::CommunicatorPtr&
@@ -934,7 +1164,6 @@ public:
return _communicator();
}
-
protected:
Map(const Ice::CommunicatorPtr& communicator) :
@@ -957,16 +1186,20 @@ namespace std
{
// TODO: update.
-template <class key_type, class mapped_type, class KeyCodec, class ValueCodec>
+template <class key_type, class mapped_type,
+ class KeyCodec, class ValueCodec, class Compare>
inline pair<const key_type, const mapped_type>*
-value_type(const Freeze::Iterator<key_type, mapped_type, KeyCodec, ValueCodec>&)
+value_type(const Freeze::Iterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>&)
{
return (pair<const key_type, const mapped_type>*)0;
}
-template <class key_type, class mapped_type, class KeyCodec, class ValueCodec>
+template <class key_type, class mapped_type,
+ class KeyCodec, class ValueCodec, class Compare>
inline pair<const key_type, const mapped_type>*
-value_type(const Freeze::ConstIterator<key_type, mapped_type, KeyCodec, ValueCodec>&)
+value_type(const Freeze::ConstIterator<key_type, mapped_type,
+ KeyCodec, ValueCodec, Compare>&)
{
return (pair<const key_type, const mapped_type>*)0;
}
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);
diff --git a/cpp/test/Freeze/dbmap/Client.cpp b/cpp/test/Freeze/dbmap/Client.cpp
index d2235fb5870..1dad4cca175 100644
--- a/cpp/test/Freeze/dbmap/Client.cpp
+++ b/cpp/test/Freeze/dbmap/Client.cpp
@@ -13,6 +13,7 @@
#include <ByteIntMap.h>
#include <IntIdentityMap.h>
#include <IntIdentityMapWithIndex.h>
+#include <SortedMap.h>
#include <Freeze/TransactionHolder.h>
#include <algorithm>
@@ -199,8 +200,9 @@ private:
int
-run(const CommunicatorPtr& communicator, const string& envName, const string& dbName)
+run(const CommunicatorPtr& communicator, const string& envName)
{
+ const string dbName = "binary";
Freeze::ConnectionPtr connection = createConnection(communicator, envName);
ByteIntMap m(connection, dbName);
@@ -617,6 +619,110 @@ run(const CommunicatorPtr& communicator, const string& envName, const string& db
}
iim.clear();
}
+ cout << "ok" << endl;
+
+ cout << "testing sorting... " << flush;
+ {
+ SortedMap sm(connection, "sortedIntIdentity");
+
+ TransactionHolder txHolder(connection);
+ for(int i = 0; i < 1000; i++)
+ {
+ int k = rand() % 1000;
+
+ Ice::Identity id;
+ id.name = "foo";
+ id.category = 'a' + static_cast<char>(k % 26);
+
+ sm.put(SortedMap::value_type(k, id));
+ }
+ txHolder.commit();
+ }
+
+ {
+ SortedMap sm(connection, "sortedIntIdentity");
+ {
+ for(int i = 0; i < 100; ++i)
+ {
+ int k = rand() % 1000;
+ SortedMap::iterator p = sm.lower_bound(k);
+ if(p != sm.end())
+ {
+ test(p->first >= k);
+ SortedMap::iterator q = sm.upper_bound(k);
+ if(q == sm.end())
+ {
+ test(p->first == k);
+ }
+ else
+ {
+ test((p->first == k && q->first > k) ||
+ (p->first > k && q->first == p->first));
+ }
+ }
+ }
+ }
+
+ {
+ for(int i = 0; i < 100; ++i)
+ {
+ string category;
+ category = static_cast<char>('a' + rand() % 26);
+
+ SortedMap::iterator p = sm.findByCategory(category);
+ if(p != sm.end())
+ {
+ SortedMap::iterator q = sm.lowerBoundForCategory(category);
+ test(p == q);
+ do
+ {
+ q++;
+ } while(q != sm.end() && q->second.category == category);
+
+ if(q != sm.end())
+ {
+ test(q == sm.upperBoundForCategory(category));
+ }
+ }
+ else
+ {
+ SortedMap::iterator q = sm.lowerBoundForCategory(category);
+ if(q != sm.end())
+ {
+ test(p != q);
+ test(q->second.category < category);
+ category = q->second.category;
+
+ do
+ {
+ q++;
+ } while(q != sm.end() && q->second.category == category);
+
+ if(q != sm.end())
+ {
+ test(q == sm.upperBoundForCategory(category));
+ }
+ }
+ }
+ }
+ }
+
+ {
+ string category = "z";
+ SortedMap::iterator p = sm.lowerBoundForCategory(category);
+
+ while(p != sm.end())
+ {
+ test(p->second.category <= category);
+ category = p->second.category;
+ // cerr << category << ":" << p->first << endl;
+ ++p;
+ }
+ }
+
+ sm.clear();
+ }
+
cout << "ok" << endl;
@@ -641,7 +747,7 @@ main(int argc, char* argv[])
envName += "db";
}
- status = run(communicator, envName, "binary");
+ status = run(communicator, envName);
}
catch(const Ice::Exception& ex)
{
diff --git a/cpp/test/Freeze/dbmap/Makefile b/cpp/test/Freeze/dbmap/Makefile
index 8d79e39b1e4..ebe39a3e43a 100644
--- a/cpp/test/Freeze/dbmap/Makefile
+++ b/cpp/test/Freeze/dbmap/Makefile
@@ -16,7 +16,8 @@ TARGETS = $(CLIENT)
OBJS = Client.o \
ByteIntMap.o \
IntIdentityMap.o \
- IntIdentityMapWithIndex.o
+ IntIdentityMapWithIndex.o \
+ SortedMap.o
SRCS = $(OBJS:.o=.cpp)
@@ -40,9 +41,12 @@ IntIdentityMapWithIndex.h IntIdentityMapWithIndex.cpp: $(SLICE2FREEZE)
rm -f IntIdentityMapWithIndex.h IntIdentityMapWithIndex.cpp
$(SLICE2FREEZE) --ice $(SLICE2CPPFLAGS) --dict Test::IntIdentityMapWithIndex,int,Ice::Identity --dict-index Test::IntIdentityMapWithIndex,category IntIdentityMapWithIndex $(slicedir)/Ice/Identity.ice
+SortedMap.h SortedMap.cpp: $(SLICE2FREEZE)
+ rm -f SortedMap.h SortedMap.cpp
+ $(SLICE2FREEZE) --ice $(SLICE2CPPFLAGS) --dict Test::SortedMap,int,Ice::Identity,sort SortedMap --dict-index "Test::SortedMap,category,sort,std::greater<std::string>" $(slicedir)/Ice/Identity.ice
clean::
- rm -f ByteIntMap.h ByteIntMap.cpp IntIdentityMap.h IntIdentityMap.cpp IntIdentityMapWithIndex.h IntIdentityMapWithIndex.cpp
+ rm -f ByteIntMap.h ByteIntMap.cpp IntIdentityMap.h IntIdentityMap.cpp IntIdentityMapWithIndex.h IntIdentityMapWithIndex.cpp SortedMap.h SortedMap.cpp
clean::
rm -f db/binary db/binary.* db/intIdentity db/intIdentity.* db/__catalog db/log.*
diff --git a/cpp/test/Freeze/dbmap/dbmap.dsp b/cpp/test/Freeze/dbmap/dbmap.dsp
index b619a4f9656..1b19776f9d4 100644
--- a/cpp/test/Freeze/dbmap/dbmap.dsp
+++ b/cpp/test/Freeze/dbmap/dbmap.dsp
@@ -25,7 +25,7 @@ CFG=dbmap - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "dbmap - Win32 Release"
@@ -49,7 +49,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 /nologo /subsystem:console /incremental:yes /machine:I386 /out:"client.exe" /libpath:"../../../lib" /FIXED:no
# SUBTRACT LINK32 /debug /nodefaultlib
@@ -75,7 +75,7 @@ LINK32=link.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"client.exe" /pdbtype:sept /libpath:"../../../lib" /FIXED:no
# SUBTRACT LINK32 /pdb:none
@@ -105,6 +105,10 @@ SOURCE=.\IntIdentityMap.cpp
SOURCE=.\IntIdentityMapWithIndex.cpp
# End Source File
+# Begin Source File
+
+SOURCE=.\SortedMap.cpp
+# End Source File
# End Group
# Begin Group "Header Files"
@@ -139,6 +143,7 @@ BuildCmds= \
..\..\..\bin\slice2freeze.exe --dict Test::ByteIntMap,byte,int --dict-index Test::ByteIntMap ByteIntMap \
..\..\..\bin\slice2freeze.exe --ice -I../../../slice --dict Test::IntIdentityMap,int,Ice::Identity IntIdentityMap ../../../slice/Ice/Identity.ice \
..\..\..\bin\slice2freeze.exe --ice -I../../../slice --dict Test::IntIdentityMapWithIndex,int,Ice::Identity IntIdentityMapWithIndex --dict-index Test::IntIdentityMapWithIndex,category ../../../slice/Ice/Identity.ice \
+ ..\..\..\bin\slice2freeze.exe --ice -I../../../slice --dict Test::SortedMap,int,Ice::Identity,sort SortedMap --dict-index "Test::SortedMap,category,sort,std::greater<std::string>" ../../../slice/Ice/Identity.ice \
"ByteIntMap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
@@ -158,6 +163,12 @@ BuildCmds= \
"IntIdentityMapWithIndex.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
+
+"SortedMap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"SortedMap.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "dbmap - Win32 Debug"
@@ -170,6 +181,7 @@ BuildCmds= \
..\..\..\bin\slice2freeze.exe --dict Test::ByteIntMap,byte,int --dict-index Test::ByteIntMap ByteIntMap \
..\..\..\bin\slice2freeze.exe --ice -I../../../slice --dict Test::IntIdentityMap,int,Ice::Identity IntIdentityMap ../../../slice/Ice/Identity.ice \
..\..\..\bin\slice2freeze.exe --ice -I../../../slice --dict Test::IntIdentityMapWithIndex,int,Ice::Identity IntIdentityMapWithIndex --dict-index Test::IntIdentityMapWithIndex,category ../../../slice/Ice/Identity.ice \
+ ..\..\..\bin\slice2freeze.exe --ice -I../../../slice --dict Test::SortedMap,int,Ice::Identity,sort SortedMap --dict-index "Test::SortedMap,category,sort,std::greater<std::string>" ../../../slice/Ice/Identity.ice \
"ByteIntMap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
@@ -189,6 +201,12 @@ BuildCmds= \
"IntIdentityMapWithIndex.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
+
+"SortedMap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"SortedMap.cpp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
# End Custom Build
!ENDIF