diff --git a/src/org/apache/cassandra/service/BootstrapAndLbHelper.java b/src/org/apache/cassandra/service/BootstrapAndLbHelper.java new file mode 100644 index 0000000000..79bcc17156 --- /dev/null +++ b/src/org/apache/cassandra/service/BootstrapAndLbHelper.java @@ -0,0 +1,64 @@ + /** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cassandra.service; + +import java.math.BigInteger; +import java.util.Iterator; +import java.util.List; + +import org.apache.cassandra.io.SSTable; +import org.apache.log4j.Logger; + +public final class BootstrapAndLbHelper +{ + private static final Logger logger_ = Logger.getLogger(BootstrapAndLbHelper.class); + private static List getIndexedPrimaryKeys() + { + List indexedPrimaryKeys = SSTable.getIndexedKeys(); + Iterator it = indexedPrimaryKeys.iterator(); + + while ( it.hasNext() ) + { + String key = it.next(); + if ( !StorageService.instance().isPrimary(key) ) + { + it.remove(); + } + } + return indexedPrimaryKeys; + } + + /** + * Given the number of keys that need to be transferred say, 1000 + * and given the smallest key stored we need the hash of the 1000th + * key greater than the smallest key in the sorted order in the primary + * range. + * + * @param keyCount number of keys after which token is required. + * @return token. + */ + public static BigInteger getTokenBasedOnPrimaryCount(int keyCount) + { + List indexedPrimaryKeys = getIndexedPrimaryKeys(); + int index = keyCount / SSTable.indexInterval(); + String key = (index >= indexedPrimaryKeys.size()) ? indexedPrimaryKeys.get( indexedPrimaryKeys.size() - 1 ) : indexedPrimaryKeys.get(index); + logger_.debug("Hashing key " + key + " ..."); + return StorageService.instance().hash(key); + } +} diff --git a/src/org/apache/cassandra/service/IPartitioner.java b/src/org/apache/cassandra/service/IPartitioner.java new file mode 100644 index 0000000000..bee726d4e6 --- /dev/null +++ b/src/org/apache/cassandra/service/IPartitioner.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cassandra.service; + +import java.math.BigInteger; + +public interface IPartitioner +{ + public BigInteger hash(String key); +} diff --git a/src/org/apache/cassandra/service/LocationInfoVerbHandler.java b/src/org/apache/cassandra/service/LocationInfoVerbHandler.java new file mode 100644 index 0000000000..40a0d1653e --- /dev/null +++ b/src/org/apache/cassandra/service/LocationInfoVerbHandler.java @@ -0,0 +1,83 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cassandra.service; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.dht.Range; +import org.apache.cassandra.gms.FailureDetector; +import org.apache.cassandra.io.DataInputBuffer; +import org.apache.cassandra.locator.TokenMetadata; +import org.apache.cassandra.net.CompactEndPointSerializationHelper; +import org.apache.cassandra.net.EndPoint; +import org.apache.cassandra.net.IVerbHandler; +import org.apache.cassandra.net.Message; +import org.apache.cassandra.net.MessagingService; +import org.apache.cassandra.utils.LogUtil; +import org.apache.log4j.Logger; + +/** + * Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com ) + */ + +public class LocationInfoVerbHandler implements IVerbHandler +{ + private static Logger logger_ = Logger.getLogger( LocationInfoVerbHandler.class ); + + public void doVerb(Message message) + { + EndPoint from = message.getFrom(); + logger_.info("Received a location download request from " + from); + + Object[] body = message.getMessageBody(); + byte[] bytes = (byte[])body[0]; + DataInputBuffer bufIn = new DataInputBuffer(); + bufIn.reset(bytes, bytes.length); + try + { + Range range = Range.serializer().deserialize(bufIn); + /* Get the replicas for the given range */ + EndPoint[] replicas = StorageService.instance().getNStorageEndPoint(range.right()); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + + for ( EndPoint replica : replicas ) + { + replica.setPort(DatabaseDescriptor.getControlPort()); + if ( FailureDetector.instance().isAlive(replica) ) + { + replica.setPort(DatabaseDescriptor.getStoragePort()); + CompactEndPointSerializationHelper.serialize(replica, dos); + break; + } + } + + Message response = message.getReply(StorageService.getLocalStorageEndPoint(), new Object[]{bos.toByteArray()}); + logger_.info("Sending the token download response to " + from); + MessagingService.getMessagingInstance().sendOneWay(response, from); + } + catch (IOException ex) + { + logger_.warn(LogUtil.throwableToString(ex)); + } + } +} diff --git a/src/org/apache/cassandra/service/OrderPreservingHashPartitioner.java b/src/org/apache/cassandra/service/OrderPreservingHashPartitioner.java new file mode 100644 index 0000000000..89d0041c61 --- /dev/null +++ b/src/org/apache/cassandra/service/OrderPreservingHashPartitioner.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cassandra.service; + +import java.math.BigInteger; + +public class OrderPreservingHashPartitioner implements IPartitioner +{ + private final static int maxKeyHashLength_ = 36; + private final static BigInteger ONE = BigInteger.ONE; + /* May be even 255L will work. But I need to verify that. */ + private static final BigInteger prime_ = BigInteger.valueOf(Character.MAX_VALUE); + + public BigInteger hash(String key) + { + BigInteger h = BigInteger.ZERO; + char val[] = key.toCharArray(); + + for (int i = 0; i < maxKeyHashLength_; i++) + { + if( i < val.length ) + h = prime_.multiply(h).add( BigInteger.valueOf(val[i]) ); + else + h = prime_.multiply(h).add( ONE ); + } + return h; + } +} diff --git a/src/org/apache/cassandra/service/RandomPartitioner.java b/src/org/apache/cassandra/service/RandomPartitioner.java new file mode 100644 index 0000000000..3b7e9363d3 --- /dev/null +++ b/src/org/apache/cassandra/service/RandomPartitioner.java @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cassandra.service; + +import java.math.BigInteger; + +import org.apache.cassandra.utils.FBUtilities; + +/** + * This class generates a MD5 hash of the key. It uses the standard technique + * used in all DHT's. + * + * @author alakshman + * + */ +public class RandomPartitioner implements IPartitioner +{ + public BigInteger hash(String key) + { + return FBUtilities.hash(key); + } +} \ No newline at end of file diff --git a/src/org/apache/cassandra/service/TokenInfoVerbHandler.java b/src/org/apache/cassandra/service/TokenInfoVerbHandler.java new file mode 100644 index 0000000000..cc3c242c86 --- /dev/null +++ b/src/org/apache/cassandra/service/TokenInfoVerbHandler.java @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cassandra.service; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.cassandra.locator.TokenMetadata; +import org.apache.cassandra.net.EndPoint; +import org.apache.cassandra.net.IVerbHandler; +import org.apache.cassandra.net.Message; +import org.apache.cassandra.net.MessagingService; +import org.apache.cassandra.utils.LogUtil; +import org.apache.log4j.Logger; + +/** + * Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com ) + */ + +public class TokenInfoVerbHandler implements IVerbHandler +{ + private static Logger logger_ = Logger.getLogger( TokenInfoVerbHandler.class ); + + public void doVerb(Message message) + { + EndPoint from = message.getFrom(); + logger_.info("Received a token download request from " + from); + /* Get the token metadata map and send it over. */ + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + try + { + TokenMetadata.serializer().serialize( StorageService.instance().getTokenMetadata(), dos ); + Message response = message.getReply(StorageService.getLocalStorageEndPoint(), new Object[]{bos.toByteArray()}); + logger_.info("Sending the token download response to " + from); + MessagingService.getMessagingInstance().sendOneWay(response, from); + } + catch ( IOException ex ) + { + logger_.info( LogUtil.throwableToString(ex) ); + } + } +}