/**
* Copyright 2005-2012 Akiban Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.persistit.policy;
import com.persistit.Buffer;
/**
* Policies for determining the balance between left and right pages when
* rebalancing page content due to deletion.
*
* @version 1.0
*/
public class JoinPolicy {
/**
* Maximize the number of records in the left page, and minimize the number
* of records in the right page.
*/
public final static JoinPolicy LEFT_BIAS = new JoinPolicy(-1, "LEFT");
/**
* Minimize the number of records in the left page, and maximize the number
* of records in the right page.
*/
public final static JoinPolicy RIGHT_BIAS = new JoinPolicy(1, "RIGHT");
/**
* Balance the allocation of spaces evenly between left and right pages.
*/
public final static JoinPolicy EVEN_BIAS = new JoinPolicy(0, "EVEN");
private final static JoinPolicy[] POLICIES = { LEFT_BIAS, RIGHT_BIAS, EVEN_BIAS };
public static JoinPolicy forName(final String name) {
for (final JoinPolicy policy : POLICIES) {
if (policy.toString().equalsIgnoreCase(name)) {
return policy;
}
}
throw new IllegalArgumentException("No such SplitPolicy " + name);
}
String _name;
int _bias;
protected JoinPolicy(final int bias, final String name) {
_bias = bias;
_name = name;
}
/**
* Determines the quality of fit for a specified candidate join location
* within a page. Returns 0 if no join is possible, or a positive integer if
* a join is possible. The caller will call joinFit to evaluate several
* possible join locations, and will choose the one yielding the largest
* value of this method.
*
* @param leftBuffer
* The left <code>Buffer></code>
* @param rightBuffer
* The right <code>Buffer</code>
* @param kbOffset
* The key block proposed as the new split point
* @param foundAt1
* First key being deleted from left page
* @param foundAt2
* First key not being deleted from right page
* @param virtualSize
* The total size of both pages
* @param leftSize
* Size the left page would have if split here
* @param rightSize
* Size the right page would have if split here
* @param capacity
* The total space available in a page (less overhead)
* @return A measure of "goodness of fit" This method should return the
* largest such measure for the best split point
*/
public int rebalanceFit(final Buffer leftBuffer, final Buffer rightBuffer, final int kbOffset, final int foundAt1,
final int foundAt2, final int virtualSize, final int leftSize, final int rightSize, final int capacity) {
//
// This implementation minimizes the difference -- i.e., attempts
// to join the page into equally sized siblings.
//
if (leftSize > capacity || rightSize > capacity)
return 0;
int fitness;
switch (_bias) {
case -1:
fitness = leftSize;
break;
case 0:
int difference = rightSize - leftSize;
if (difference < 0)
difference = -difference;
fitness = capacity - difference;
break;
case 1:
fitness = rightSize;
break;
default:
throw new IllegalArgumentException("Invalid bias");
}
return fitness;
}
/**
* Determines whether two pages will be permitted to be rejoined during a
* delete operation.
*
* @param buffer
* @param virtualSize
* @return <code>true</code> if the buffer will accept content of the
* specified size
*/
public boolean acceptJoin(final Buffer buffer, final int virtualSize) {
return virtualSize < buffer.getBufferSize();
}
/**
* @return name of the policy
*/
public String getName() {
return _name;
}
}