-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ALLUXIO-2226] Add a LocalFirstPolicy that without evict action #4445
Changes from 14 commits
64cd763
3bdc29e
8be64bc
6bf0036
536e530
f8516e6
9a16b08
065e2b1
b882567
d4dc9e1
3e50fdb
6bddccf
0d46e58
c80466e
716452f
a263a4e
6699389
26ef84c
d38b7e6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/* | ||
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 | ||
* (the "License"). You may not use this work except in compliance with the License, which is | ||
* available at www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
* either express or implied, as more fully set forth in the License. | ||
* | ||
* See the NOTICE file distributed with this work for information regarding copyright ownership. | ||
*/ | ||
|
||
package alluxio.client.file.policy; | ||
|
||
import alluxio.Configuration; | ||
import alluxio.PropertyKey; | ||
import alluxio.client.block.BlockWorkerInfo; | ||
import alluxio.util.network.NetworkAddressUtils; | ||
import alluxio.wire.WorkerNetAddress; | ||
|
||
import com.google.common.base.Objects; | ||
import com.google.common.collect.Lists; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import javax.annotation.concurrent.ThreadSafe; | ||
/** | ||
* A policy that returns local host first, and if the local worker doesn't have enough availability, | ||
* it randomly picks a worker from the active workers list for each block write. | ||
* If No worker meets the demands, return local host. | ||
* USER_FILE_WRITE_AVOID_EVICTION_POLICY_RESERVED_BYTES is used to reserve some space of the worker | ||
* to store the block, for the values mCapacityBytes minus mUsedBytes is not the available bytes. | ||
*/ | ||
@ThreadSafe | ||
public final class LocalFirstAvoidEvictionPolicy implements FileWriteLocationPolicy { | ||
private String mLocalHostName; | ||
/** | ||
* Constructs a {@link LocalFirstAvoidEvictionPolicy}. | ||
*/ | ||
public LocalFirstAvoidEvictionPolicy() { | ||
mLocalHostName = NetworkAddressUtils.getLocalHostName(); | ||
} | ||
|
||
@Override | ||
public WorkerNetAddress getWorkerForNextBlock(Iterable<BlockWorkerInfo> workerInfoList, | ||
long blockSizeBytes) { | ||
// try the local host first | ||
WorkerNetAddress localWorkerNetAddress = null; | ||
for (BlockWorkerInfo workerInfo : workerInfoList) { | ||
if (workerInfo.getNetAddress().getHost().equals(mLocalHostName)) { | ||
localWorkerNetAddress = workerInfo.getNetAddress(); | ||
if (getAvailableBytes(workerInfo) >= blockSizeBytes) { | ||
return localWorkerNetAddress; | ||
} | ||
} | ||
} | ||
|
||
// otherwise randomly pick a worker that has enough availability | ||
List<BlockWorkerInfo> shuffledWorkers = Lists.newArrayList(workerInfoList); | ||
Collections.shuffle(shuffledWorkers); | ||
for (BlockWorkerInfo workerInfo : shuffledWorkers) { | ||
if (getAvailableBytes(workerInfo) >= blockSizeBytes) { | ||
return workerInfo.getNetAddress(); | ||
} | ||
} | ||
return localWorkerNetAddress; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if there was no worker on the local host? That means There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gpang After long deliberation, if no worker on the local host and have on worker have available capacity to store the block, it should pick a random worker. When no worker in this cluster, it should return null. Thanks for you remind, it make sense. |
||
} | ||
|
||
/** | ||
* @param workerInfo BlockWorkerInfo of the worker | ||
* @return the available bytes of the worker | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please comment how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My original idea is use the variable mCapacityBytes minus mUsedBytes of class BlockWorkerInfo to get the valid Bytes of the worker. But yupeng9 tell me that this way does not actually get the available Bytes for the information of class BlockWorkerInfo is update only after a file is completely write. So, he suggest me to reserve some space to store the block. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will comment above describe to the method. Thanks for you advise. |
||
*/ | ||
private long getAvailableBytes(BlockWorkerInfo workerInfo) { | ||
long mUserFileWriteCapacityReserved = Configuration | ||
.getBytes(PropertyKey.USER_FILE_WRITE_AVOID_EVICTION_POLICY_RESERVED_BYTES); | ||
long mCapacityBytes = workerInfo.getCapacityBytes(); | ||
long mUsedBytes = workerInfo.getUsedBytes(); | ||
return mCapacityBytes - mUsedBytes - mUserFileWriteCapacityReserved; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (!(o instanceof LocalFirstAvoidEvictionPolicy)) { | ||
return false; | ||
} | ||
LocalFirstAvoidEvictionPolicy that = (LocalFirstAvoidEvictionPolicy) o; | ||
return Objects.equal(mLocalHostName, that.mLocalHostName); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hashCode(mLocalHostName); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return Objects.toStringHelper(this) | ||
.add("localHostName", mLocalHostName) | ||
.toString(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 | ||
* (the "License"). You may not use this work except in compliance with the License, which is | ||
* available at www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
* either express or implied, as more fully set forth in the License. | ||
* | ||
* See the NOTICE file distributed with this work for information regarding copyright ownership. | ||
*/ | ||
|
||
package alluxio.client.file.policy; | ||
|
||
import alluxio.CommonTestUtils; | ||
import alluxio.Constants; | ||
import alluxio.client.block.BlockWorkerInfo; | ||
import alluxio.util.network.NetworkAddressUtils; | ||
import alluxio.wire.WorkerNetAddress; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
* Tests {@link LocalFirstAvoidEvictionPolicy}. | ||
*/ | ||
public class LocalFirstAvoidEvictionPolicyTest { | ||
private static final int PORT = 1; | ||
|
||
/** | ||
* Tests that the local host is returned first. | ||
*/ | ||
@Test | ||
public void getLocalFirst() { | ||
String localhostName = NetworkAddressUtils.getLocalHostName(); | ||
LocalFirstAvoidEvictionPolicy policy = new LocalFirstAvoidEvictionPolicy(); | ||
List<BlockWorkerInfo> workerInfoList = new ArrayList<>(); | ||
workerInfoList.add(new BlockWorkerInfo(new WorkerNetAddress().setHost("worker1") | ||
.setRpcPort(PORT).setDataPort(PORT).setWebPort(PORT), Constants.GB, 0)); | ||
workerInfoList.add(new BlockWorkerInfo(new WorkerNetAddress().setHost(localhostName) | ||
.setRpcPort(PORT).setDataPort(PORT).setWebPort(PORT), Constants.GB, 0)); | ||
Assert.assertEquals(localhostName, | ||
policy.getWorkerForNextBlock(workerInfoList, Constants.MB).getHost()); | ||
} | ||
|
||
/** | ||
* Tests that another worker is picked in case the local host does not have enough space. | ||
*/ | ||
@Test | ||
public void getOthersWhenNotEnoughSpaceOnLocal() { | ||
String localhostName = NetworkAddressUtils.getLocalHostName(); | ||
LocalFirstAvoidEvictionPolicy policy = new LocalFirstAvoidEvictionPolicy(); | ||
List<BlockWorkerInfo> workerInfoList = new ArrayList<>(); | ||
workerInfoList.add(new BlockWorkerInfo(new WorkerNetAddress().setHost("worker1") | ||
.setRpcPort(PORT).setDataPort(PORT).setWebPort(PORT), Constants.GB, 0)); | ||
workerInfoList.add(new BlockWorkerInfo(new WorkerNetAddress().setHost(localhostName) | ||
.setRpcPort(PORT).setDataPort(PORT).setWebPort(PORT), Constants.MB, Constants.MB)); | ||
Assert.assertEquals("worker1", | ||
policy.getWorkerForNextBlock(workerInfoList, Constants.MB).getHost()); | ||
} | ||
|
||
/** | ||
* Tests that local host is picked if none of the workers has enough availability. | ||
*/ | ||
@Test | ||
public void getLocalWhenNoneHasSpace() { | ||
String localhostName = NetworkAddressUtils.getLocalHostName(); | ||
LocalFirstAvoidEvictionPolicy policy = new LocalFirstAvoidEvictionPolicy(); | ||
List<BlockWorkerInfo> workerInfoList = new ArrayList<>(); | ||
workerInfoList.add(new BlockWorkerInfo(new WorkerNetAddress().setHost("worker1") | ||
.setRpcPort(PORT).setDataPort(PORT).setWebPort(PORT), Constants.GB, Constants.MB)); | ||
workerInfoList.add(new BlockWorkerInfo(new WorkerNetAddress().setHost(localhostName) | ||
.setRpcPort(PORT).setDataPort(PORT).setWebPort(PORT), Constants.GB, Constants.MB)); | ||
Assert.assertEquals(localhostName, | ||
policy.getWorkerForNextBlock(workerInfoList, Constants.GB).getHost()); | ||
} | ||
|
||
@Test | ||
public void equalsTest() throws Exception { | ||
CommonTestUtils.testEquals(LocalFirstAvoidEvictionPolicy.class); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also specify the behavior of
USER_FILE_WRITE_CAPACITY_RESERVED_SIZE_BYTES
?