Skip to content

Commit af447a4

Browse files
author
Ryan CrawCour
committed
Merge pull request #38 from rnagpal/master
Master
2 parents e63a54b + 95fdb3d commit af447a4

21 files changed

+1976
-64
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ target/
1010
*.war
1111
*.ear
1212

13+
# Visual Studio test files
14+
src/com/microsoft/azure/documentdb/test/JavaTestCases.xml
15+
src/com/microsoft/azure/documentdb/test/SingleJUnitTestRunner.java
16+
1317
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
1418
hs_err_pid*
1519

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w
1414
<dependency>
1515
<groupId>com.microsoft.azure</groupId>
1616
<artifactId>azure-documentdb</artifactId>
17-
<version>1.4.0</version>
17+
<version>1.5.0</version>
1818
</dependency>
1919

2020
###Option 2: Source Via Git

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Changes in 1.5.0 : ##
2+
3+
- Added Client-side sharding framework to the SDK. Implemented HashPartionResolver and RangePartitionResolver classes.
4+
15
## Changes in 1.4.0 : ##
26

37
- Implement Upsert. New upsertXXX methods added to support Upsert feature.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.microsoft.azure</groupId>
55
<artifactId>azure-documentdb</artifactId>
6-
<version>1.4.0</version>
6+
<version>1.5.0</version>
77
<name>${project.groupId}:${project.artifactId}</name>
88
<description>Java SDK for Microsoft Azure DocumentDB</description>
99
<url>http://azure.microsoft.com/en-us/services/documentdb/</url>
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
The MIT License (MIT)
3+
Copyright (c) 2014 Microsoft Corporation
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+
*/
23+
24+
package com.microsoft.azure.documentdb;
25+
26+
import java.io.UnsupportedEncodingException;
27+
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
30+
/**
31+
* The ConsistentHashRing class internally implements a consistent hash ring using the hash function specified
32+
*/
33+
final class ConsistentHashRing {
34+
private HashGenerator hashGenerator;
35+
private Partition[] partitions;
36+
private ArrayList<String> collectionLinks = new ArrayList<String>();
37+
38+
/**
39+
* ConsistentHashRing constructor taking in the collection links, total number of partitions
40+
* and hash generator to initialize the ring.
41+
*
42+
* @param collectionLinks the links of collections participating in partitioning.
43+
* @param totalPartitions the total number of partitions.
44+
* @param hashGenerator the hash generator to be used for hashing algorithm.
45+
*/
46+
public ConsistentHashRing(Iterable<String> collectionLinks, int totalPartitions, HashGenerator hashGenerator) {
47+
if(collectionLinks == null) {
48+
throw new IllegalArgumentException("collectionLinks");
49+
}
50+
51+
for(String collectionLink : collectionLinks) {
52+
this.collectionLinks.add(collectionLink);
53+
}
54+
55+
if(totalPartitions < this.collectionLinks.size()) {
56+
throw new IllegalArgumentException("The total number of partitions must be at least the number of collections.");
57+
}
58+
59+
if(hashGenerator == null) {
60+
throw new IllegalArgumentException("hashGenerator");
61+
}
62+
63+
this.hashGenerator = hashGenerator;
64+
this.partitions = this.constructPartitions(this.collectionLinks, totalPartitions);
65+
}
66+
67+
/**
68+
* Gets the SelfLink/ID based link of the collection node that maps to the partition key
69+
* based on the hashing algorithm used for finding the node in the ring.
70+
*
71+
* @param partitionKey partition key to be used for finding the node in the ring.
72+
*
73+
* @return collection node SelfLink/ID based link mapped to the partition key.
74+
*/
75+
public String getCollectionNode(Object partitionKey) {
76+
if(partitionKey == null) {
77+
throw new IllegalArgumentException("partitionKey");
78+
}
79+
80+
// Find the the partition from the total partitions created for the given partition key
81+
int partition = this.findPartition(getBytes(partitionKey));
82+
83+
// Returns the name of the collection mapped to that partition
84+
return this.partitions[partition].getNode();
85+
}
86+
87+
/**
88+
* Gets the bytes representing the value of the partition key.
89+
*
90+
*/
91+
private static byte[] getBytes(Object partitionKey) {
92+
byte[] bytes = null;
93+
94+
// Currently we only support partition key to be of type String
95+
if(partitionKey instanceof String) {
96+
String str = (String)partitionKey;
97+
try {
98+
bytes = str.getBytes("UTF-8");
99+
} catch (UnsupportedEncodingException e) {
100+
// If we get this exception, we return bytes as null(as initialized)
101+
}
102+
}
103+
else {
104+
throw new UnsupportedOperationException(String.format("Unsupported type %s for partitionKey.", partitionKey.getClass()));
105+
}
106+
107+
return bytes;
108+
}
109+
110+
/**
111+
* Constructs the partitions in the consistent ring by assigning them to collection nodes
112+
* using the hashing algorithm and then finally sorting the partitions based on the hash value.
113+
*
114+
*/
115+
private Partition[] constructPartitions(ArrayList<String> collectionLinks, int totalPartitions) {
116+
int collectionsNodeCount = collectionLinks.size();
117+
Partition[] partitions = new Partition[totalPartitions];
118+
119+
int partitionsPerNode = totalPartitions/collectionsNodeCount;
120+
int extraPartitions = totalPartitions - (partitionsPerNode * collectionsNodeCount);
121+
122+
int index = 0;
123+
for(String collectionNode : collectionLinks) {
124+
byte[] hashValue = this.hashGenerator.computeHash(getBytes(collectionNode));
125+
126+
for(int i=0; i < partitionsPerNode + (extraPartitions > 0 ? 1 : 0); ++i) {
127+
partitions[index++] = new Partition(hashValue, collectionNode);
128+
hashValue = this.hashGenerator.computeHash(hashValue);
129+
}
130+
131+
extraPartitions--;
132+
}
133+
134+
Arrays.sort(partitions);
135+
return partitions;
136+
}
137+
138+
/**
139+
* Finds the partition from the byte array representation of the partition key.
140+
*
141+
*/
142+
private int findPartition(byte[] key) {
143+
byte[] hashValue = this.hashGenerator.computeHash(key);
144+
return lowerBoundSearch(this.partitions, hashValue);
145+
}
146+
147+
/**
148+
* Searches the partition in the partition array using hashValue
149+
* and returns the lower bound index
150+
*
151+
*/
152+
private static int lowerBoundSearch(Partition[] partitions, byte[] hashValue) {
153+
for(int i=0; i<partitions.length-1; i++) {
154+
if(partitions[i].compareTo(hashValue) <= 0 && partitions[i+1].compareTo(hashValue) > 0) {
155+
return i;
156+
}
157+
}
158+
159+
return partitions.length-1;
160+
}
161+
}

0 commit comments

Comments
 (0)