By default, GemFire partitions each data entry into a bucket using a hashing policy on the key. Additionally, the physical location of the key-value pair is abstracted away from the application. You can change these policies for a partitioned region. You can provide your own data partitioning resolver and you can additionally specify which members host which data buckets.
For standard partitioning, you use com.gemstone.gemfire.cache.PartitionResolver. To implement fixed partitioning, you use com.gemstone.gemfire.cache.FixedPartitionResolver.
For example, here is an implementation on a region key object that groups the entries by month and year:
Public class TradeKey implements PartitionResolver
{
private String tradeID;
private Month month;
private Year year;
public TradingKey(){ }
public TradingKey(Month month, Year year)
{
this.month = month;
this.year = year;
}
public Serializable getRoutingObject(EntryOperation opDetails)
{
return this.month + this.year;
}
}
These examples set the partition attributes for a member to be the primary host for the "Q1" partition data and a secondary host for "Q3" partition data.
XML:<cache>
<region name="Trades">
<region-attributes>
<partition-attributes redundant-copies="1"
partition-resolver= "QuarterFixedPartitionResolver">
<fixed-partition-attributes partition-name="Q1" is-primary="true"/>
<fixed-partition-attributes partition-name="Q3" is-primary="false" num-buckets="6"/>
</partition-attributes>
</region-attributes>
</region>
</cache>
Java:
FixedPartitionAttribute fpa1 = FixedPartitionAttributes.createFixedPartition("Q1", true);
FixedPartitionAttribute fpa3 = FixedPartitionAttributes.createFixedPartition("Q3", false, 6);
PartitionAttributesFactory paf = new PartitionAttributesFactory()
.setPartitionResolver(new QuarterFixedPartitionResolver())
.setTotalNumBuckets(12)
.setRedundantCopies(2)
.addFixedPartitionAttribute(fpa1)
.addFixedPartitionAttribute(fpa3);
AttributesFactory attrFactory = new AttributesFactory();
attrFactory.setPartitionAttributes(paf.create());
DistributedSystem system = DistributedSystem.connect(new Properties());
Cache cache = CacheFactory.create(system);
Region createRegion = cache.createRegion("Trades", attrFactory.create());
Region<String, String> region = (PartitionedRegion)createRegion;
/**
* Returns one of four different partition names
* (Q1, Q2, Q3, Q4) depending on the entry's date
*/
class QuarterFixedPartitionResolver implements
FixedPartitionResolver<String, String> {
@Override
public String getPartitionName(EntryOperation<String, String> opDetails,
Set<String> targetPartitions) {
Date date = (Date)opDetails.getKey();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);
if (month >= 0 && month < 3) {
if (targetPartitions.contains("Q1")) return "Q1";
}
else if (month >= 3 && month < 6) {
if (targetPartitions.contains("Q2")) return "Q2";
}
else if (month >= 6 && month < 9) {
if (targetPartitions.contains("Q3")) return "Q3";
}
else if (month >= 9 && month < 12) {
if (targetPartitions.contains("Q4")) return "Q4";
}
return "Invalid Quarter";
}
@Override
public String getName() {
return "QuarterFixedPartitionResolver";
}
@Override
public Serializable getRoutingObject(EntryOperation<String, String> opDetails) {
Date date = (Date)opDetails.getKey();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);
return month;
}
@Override
public void close() {
}
}
<region name="trades">
<region-attributes>
<partition-attributes>
<partition-resolver="TradesPartitionResolver">
<class-name>myPackage.TradesPartitionResolver
</class-name>
</partition-resolver>
<partition-attributes>
</region-attributes>
</region>
PartitionResolver resolver = new TradesPartitionResolver();
PartitionAttributes attrs =
new PartitionAttributesFactory()
.setPartitionResolver(resolver).create();
Region Trades =
new RegionFactory().setPartitionAttributes(attrs).create("trades");