Files
mongo/s/shardkey.cpp

162 lines
5.4 KiB
C++
Raw Normal View History

2009-02-17 14:41:31 -05:00
// shardkey.cpp
/**
* Copyright (C) 2008 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2010-04-27 15:27:52 -04:00
#include "pch.h"
#include "chunk.h"
2009-02-17 14:41:31 -05:00
#include "../db/jsobj.h"
2009-02-18 10:10:39 -05:00
#include "../util/unittest.h"
2009-02-17 14:41:31 -05:00
namespace mongo {
ShardKeyPattern::ShardKeyPattern( BSONObj p ) : pattern( p.getOwned() ) {
pattern.getFieldNames(patternfields);
BSONObjBuilder min;
BSONObjBuilder max;
2010-07-13 21:28:11 -04:00
BSONObjIterator it(p);
while (it.more()){
BSONElement e (it.next());
min.appendMinKey(e.fieldName());
max.appendMaxKey(e.fieldName());
}
gMin = min.obj();
gMax = max.obj();
}
2010-05-03 14:35:03 -04:00
int ShardKeyPattern::compare( const BSONObj& lObject , const BSONObj& rObject ) const {
BSONObj L = extractKey(lObject);
2010-07-13 21:28:11 -04:00
uassert( 10198 , "left object doesn't have full shard key", L.nFields() == (int)patternfields.size());
BSONObj R = extractKey(rObject);
2010-07-13 21:28:11 -04:00
uassert( 10199 , "right object doesn't have full shard key", R.nFields() == (int)patternfields.size());
return L.woCompare(R);
}
2010-05-03 14:35:03 -04:00
bool ShardKeyPattern::hasShardKey( const BSONObj& obj ) const {
/* this is written s.t. if obj has lots of fields, if the shard key fields are early,
it is fast. so a bit more work to try to be semi-fast.
*/
2010-05-04 17:40:40 -04:00
for(set<string>::const_iterator it = patternfields.begin(); it != patternfields.end(); ++it){
if(obj.getFieldDotted(it->c_str()).eoo())
return false;
}
return true;
2009-02-20 10:46:42 -05:00
}
2009-02-20 13:46:57 -05:00
bool ShardKeyPattern::isPrefixOf( const BSONObj& otherPattern ) const {
BSONObjIterator a( pattern );
BSONObjIterator b( otherPattern );
while ( a.more() && b.more() ){
BSONElement x = a.next();
BSONElement y = b.next();
if ( strcmp( x.fieldName() , y.fieldName() ) )
return false;
}
return ! a.more();
}
string ShardKeyPattern::toString() const {
2009-02-26 12:02:43 -05:00
return pattern.toString();
}
2009-04-27 11:20:47 -04:00
/* things to test for compound :
\ middle (deprecating?)
*/
2009-02-18 10:10:39 -05:00
class ShardKeyUnitTest : public UnitTest {
public:
void testIsPrefixOf(){
{
ShardKeyPattern k( BSON( "x" << 1 ) );
assert( ! k.isPrefixOf( BSON( "a" << 1 ) ) );
assert( k.isPrefixOf( BSON( "x" << 1 ) ) );
assert( k.isPrefixOf( BSON( "x" << 1 << "a" << 1 ) ) );
assert( ! k.isPrefixOf( BSON( "a" << 1 << "x" << 1 ) ) );
}
{
ShardKeyPattern k( BSON( "x" << 1 << "y" << 1 ) );
assert( ! k.isPrefixOf( BSON( "x" << 1 ) ) );
assert( ! k.isPrefixOf( BSON( "x" << 1 << "z" << 1 ) ) );
assert( k.isPrefixOf( BSON( "x" << 1 << "y" << 1 ) ) );
assert( k.isPrefixOf( BSON( "x" << 1 << "y" << 1 << "z" << 1 ) ) );
}
}
void hasshardkeytest() {
BSONObj x = fromjson("{ zid : \"abcdefg\", num: 1.0, name: \"eliot\" }");
ShardKeyPattern k( BSON( "num" << 1 ) );
assert( k.hasShardKey(x) );
assert( !k.hasShardKey( fromjson("{foo:'a'}") ) );
// try compound key
{
ShardKeyPattern k( fromjson("{a:1,b:-1,c:1}") );
assert( k.hasShardKey( fromjson("{foo:'a',a:'b',c:'z',b:9,k:99}") ) );
assert( !k.hasShardKey( fromjson("{foo:'a',a:'b',c:'z',bb:9,k:99}") ) );
assert( !k.hasShardKey( fromjson("{k:99}") ) );
}
}
void extractkeytest() {
2010-07-13 21:28:11 -04:00
ShardKeyPattern k( fromjson("{a:1,'sub.b':-1,'sub.c':1}") );
2010-07-13 21:28:11 -04:00
BSONObj x = fromjson("{a:1,'sub.b':2,'sub.c':3}");
assert( k.extractKey( fromjson("{a:1,sub:{b:2,c:3}}") ).woEqual(x) );
assert( k.extractKey( fromjson("{sub:{b:2,c:3},a:1}") ).woEqual(x) );
}
2009-02-18 10:10:39 -05:00
void run(){
extractkeytest();
ShardKeyPattern k( BSON( "key" << 1 ) );
2009-02-18 10:10:39 -05:00
BSONObj min = k.globalMin();
2009-02-26 12:02:43 -05:00
// cout << min.jsonString(TenGen) << endl;
2009-02-18 10:10:39 -05:00
BSONObj max = k.globalMax();
BSONObj k1 = BSON( "key" << 5 );
2009-02-18 10:10:39 -05:00
assert( k.compare( min , max ) < 0 );
assert( k.compare( min , k1 ) < 0 );
2009-02-18 10:10:39 -05:00
assert( k.compare( max , min ) > 0 );
assert( k.compare( min , min ) == 0 );
hasshardkeytest();
assert( k.hasShardKey( k1 ) );
2009-02-20 10:46:42 -05:00
assert( ! k.hasShardKey( BSON( "key2" << 1 ) ) );
BSONObj a = k1;
BSONObj b = BSON( "key" << 999 );
assert( k.compare(a,b) < 0 );
testIsPrefixOf();
// add middle multitype tests
log(1) << "shardKeyTest passed" << endl;
2009-02-18 10:10:39 -05:00
}
} shardKeyTest;
2009-02-17 14:41:31 -05:00
} // namespace mongo