@Override public Collection<Slice> getSearchSlicesSingle( String shardKey, SolrParams params, DocCollection collection) { if (shardKey == null) { // search across whole collection // TODO: this may need modification in the future when shard splitting could cause an overlap return collection.getSlices(); } String id = shardKey; int idx = shardKey.indexOf(separator); if (idx < 0) { // shardKey is a simple id, so don't do a range return Collections.singletonList( hashToSlice(Hash.murmurhash3_x86_32(id, 0, id.length(), 0), collection)); } int m1 = mask1; int m2 = mask2; String part1 = id.substring(0, idx); int bitsSepIdx = part1.indexOf(bitsSepartor); if (bitsSepIdx > 0) { int firstBits = getBits(part1, bitsSepIdx); if (firstBits >= 0) { m1 = firstBits == 0 ? 0 : (-1 << (32 - firstBits)); m2 = firstBits == 32 ? 0 : (-1 >>> firstBits); part1 = part1.substring(0, bitsSepIdx); } } // If the upper bits are 0xF0000000, the range we want to cover is // 0xF0000000 0xFfffffff int hash1 = Hash.murmurhash3_x86_32(part1, 0, part1.length(), 0); int upperBits = hash1 & m1; int lowerBound = upperBits; int upperBound = upperBits | m2; if (m1 == 0) { // no bits used from first part of key.. the code above will produce 0x000000000->0xffffffff // which only works on unsigned space, but we're using signed space. lowerBound = Integer.MIN_VALUE; upperBound = Integer.MAX_VALUE; } Range completeRange = new Range(lowerBound, upperBound); List<Slice> targetSlices = new ArrayList<Slice>(1); for (Slice slice : collection.getSlices()) { Range range = slice.getRange(); if (range != null && range.overlaps(completeRange)) { targetSlices.add(slice); } } return targetSlices; }
@Override public Collection<Slice> getSearchSlicesSingle( String shardKey, SolrParams params, DocCollection collection) { if (shardKey == null) { return collection.getActiveSlices(); } // assume the shardKey is just a slice name Slice slice = collection.getSlice(shardKey); if (slice == null) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "implicit router can't find shard " + shardKey + " in collection " + collection.getName()); } return Collections.singleton(slice); }
@Override public int getPartition(Object o) { Object docId = null; if (o instanceof SolrInputDocument) { SolrInputDocument doc = (SolrInputDocument) o; docId = doc.getFieldValue(idField); if (docId == null) throw new IllegalArgumentException( "SolrInputDocument must contain a non-null value for " + idField); } else { docId = o; } if (!(docId instanceof String)) throw new IllegalArgumentException( "Only String document IDs are supported by this Partitioner!"); DocCollection dc = getDocCollection(); Slice slice = dc.getRouter().getTargetSlice((String) docId, null, null, null, dc); return getShardIndex(slice.getName(), dc); }
protected final synchronized DocCollection getDocCollection() { if (docCollection == null) { ZkStateReader zkStateReader = getCloudSolrServer().getZkStateReader(); docCollection = zkStateReader.getClusterState().getCollection(collection); // do basic checks once DocRouter docRouter = docCollection.getRouter(); if (docRouter instanceof ImplicitDocRouter) throw new IllegalStateException( "Implicit document routing not supported by this Partitioner!"); Collection<Slice> shards = getDocCollection().getSlices(); if (shards == null || shards.size() == 0) throw new IllegalStateException( "Collection '" + collection + "' does not have any shards!"); } return docCollection; }
protected final synchronized int getShardIndex(String shardId, DocCollection dc) { if (shardIndexCache == null) shardIndexCache = new HashMap<String, Integer>(20); Integer idx = shardIndexCache.get(shardId); if (idx != null) return idx.intValue(); // meh auto-boxing int s = 0; for (Slice slice : dc.getSlices()) { if (shardId.equals(slice.getName())) { shardIndexCache.put(shardId, new Integer(s)); return s; } ++s; } throw new IllegalStateException( "Cannot find index of shard '" + shardId + "' in collection: " + collection); }
@Override public Slice getTargetSlice( String id, SolrInputDocument sdoc, String route, SolrParams params, DocCollection collection) { String shard = null; if (route != null) // if a route is already passed in, try to use it shard = route; else if (sdoc != null) { String f = getRouteField(collection); if (f != null) { Object o = sdoc.getFieldValue(f); if (o != null) shard = o.toString(); else throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "No value for field " + f + " in " + sdoc); } if (shard == null) { Object o = sdoc.getFieldValue(_ROUTE_); if (o != null) { shard = o.toString(); } } } if (shard == null) { shard = params.get(_ROUTE_); } if (shard != null) { Slice slice = collection.getSlice(shard); if (slice == null) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "No shard called =" + shard + " in " + collection); } return slice; } return null; // no shard specified... use default. }
public String getShardId(String docId) { DocCollection dc = getDocCollection(); Slice slice = dc.getRouter().getTargetSlice(docId, null, null, null, dc); return slice.getName(); }