Skip to content

Commit

Permalink
frontend: fix broken directory qos reporting
Browse files Browse the repository at this point in the history
Motivation:

The frontend can report back to a client which QoS a file will recieve
when uploaded into a specific directory.  This calculation is wrong.

Modification:

Update the frontend to use the actual policy class that the pool
(likely) uses, when calculating the QoS of a directory.

(Unfortunately, there is insufficient information to determine exactly
with which policy a file will be written; therefore, the output may
deviate from reality if a new file is accepted by a volatile pool (one
that has lsf mode precious).  That said, this patch provides a much
better description.)

Update the hard-coded metadata to include the new file QoS (volatile)
and the new directory QoS (disk+tape and volatile).

Result:

Frontend now more accurately describes the QoS of directories; i.e., the
QoS that newly written files will recieve when written into this
directory, assuming none of the targeted pools are volatile.

Target: master
Request: 4.2
Request: 4.1
Request: 4.0
Request: 3.2
Patch: https://rb.dcache.org/r/11165
Acked-by: Albert Rossi
  • Loading branch information
paulmillar committed Sep 6, 2018
1 parent 5506a64 commit d47ab2b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 18 deletions.
Expand Up @@ -21,6 +21,7 @@
import javax.ws.rs.core.MediaType;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import diskCacheV111.util.CacheException;
Expand All @@ -40,6 +41,7 @@ public class QosManagement {
public static final String DISK = "disk";
public static final String TAPE = "tape";
public static final String DISK_TAPE = "disk+tape";
public static final String VOLATILE = "volatile";
public static final String UNAVAILABLE = "unavailable";

public static List<String> cdmi_geographic_placement_provided = Arrays.asList("DE");
Expand Down Expand Up @@ -70,21 +72,15 @@ public String getQosList(@ApiParam(value = "The kind of object to query.",

// query the lis of available QoS for file objects
if ("file".equals(qosValue)) {

JSONArray list = new JSONArray(Arrays.asList(DISK, TAPE, DISK_TAPE));
JSONArray list = new JSONArray(Arrays.asList(DISK, TAPE, DISK_TAPE, VOLATILE));
json.put("name", list);

}
// query the lis of available QoS for directory objects
else if ("directory".equals(qosValue.trim())) {

JSONArray list = new JSONArray(Arrays.asList(DISK, TAPE));
JSONArray list = new JSONArray(Arrays.asList(DISK, TAPE, DISK_TAPE, VOLATILE));
json.put("name", list);


} else {
throw new NotFoundException();

}

json.put("status", "200");
Expand Down Expand Up @@ -150,6 +146,10 @@ else if (DISK_TAPE.equals(qosValue)) {
setBackendCapability(backendCapability, DISK_TAPE, Arrays.asList(TAPE), qoSMetadata);

}
else if (VOLATILE.equals(qosValue)) {
QoSMetadata qoSMetadata = new QoSMetadata("0", cdmi_geographic_placement_provided, "100");
setBackendCapability(backendCapability, VOLATILE, Arrays.asList(DISK), qoSMetadata);
}
// The QoS is not known or supported.
else {
throw new NotFoundException();
Expand Down Expand Up @@ -210,6 +210,15 @@ else if (TAPE.equals(qosValue)) {
QoSMetadata qoSMetadata = new QoSMetadata("1", cdmi_geographic_placement_provided, "600000");
setBackendCapability(backendCapability, TAPE, Arrays.asList(DISK), qoSMetadata);
}
// Set data and metadata for "Disk & TAPE" QoS
else if (DISK_TAPE.equals(qosValue)) {
QoSMetadata qoSMetadata = new QoSMetadata("2", cdmi_geographic_placement_provided, "100");
setBackendCapability(backendCapability, DISK_TAPE, Collections.emptyList(), qoSMetadata);
}
else if (VOLATILE.equals(qosValue)) {
QoSMetadata qoSMetadata = new QoSMetadata("0", cdmi_geographic_placement_provided, "100");
setBackendCapability(backendCapability, VOLATILE, Collections.emptyList(), qoSMetadata);
}
// The QoS is not known or supported.
else {
throw new NotFoundException();
Expand Down
Expand Up @@ -3,7 +3,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.InternalServerErrorException;

import diskCacheV111.util.AccessLatency;
import diskCacheV111.util.CacheException;
import diskCacheV111.util.FileLocality;
import diskCacheV111.util.RetentionPolicy;
Expand All @@ -16,6 +15,10 @@
import org.dcache.namespace.FileAttribute;
import org.dcache.namespace.FileType;
import org.dcache.pinmanager.PinManagerCountPinsMessage;
import org.dcache.pool.classic.ALRPReplicaStatePolicy;
import org.dcache.pool.classic.ReplicaStatePolicy;
import org.dcache.pool.repository.ReplicaState;
import org.dcache.pool.repository.StickyRecord;
import org.dcache.poolmanager.PoolMonitor;
import org.dcache.restful.providers.JsonFileAttributes;
import org.dcache.restful.qos.QosManagement;
Expand All @@ -26,6 +29,19 @@
* information.</p>
*/
public final class NamespaceUtils {

/*
* FIXME Here the code is assuming the pluggable behaviour of whichever
* pool a new file lands on. Currently, pools have a hard-code policy
* factory (LFSReplicaStatePolicyFactory), which yields two possibilities:
* VolatileReplicaStatePolicy if lsf is "volatile" or "transient", or
* ALRPReplicaStatePolicy otherwise.
*
* In the following statement, we assume files always land on non-volatile
* pools.
*/
private static final ReplicaStatePolicy POOL_POLICY = new ALRPReplicaStatePolicy();

/**
* <p>Add quality-of-service attributes (pinned, locality, etc.) </p>
*
Expand Down Expand Up @@ -74,14 +90,7 @@ public static void addQoSAttributes(JsonFileAttributes json,
break;

case NONE: // NONE implies the target is a directory.
if (attributes.isDefined(FileAttribute.ACCESS_LATENCY)) {
json.setCurrentQos(attributes.getAccessLatency()
== AccessLatency.ONLINE ?
QosManagement.DISK :
QosManagement.TAPE);
} else {
json.setCurrentQos(QosManagement.UNAVAILABLE);
}
json.setCurrentQos(directoryQoS(attributes));
break;

case UNAVAILABLE:
Expand All @@ -97,6 +106,18 @@ public static void addQoSAttributes(JsonFileAttributes json,
}
}

private static String directoryQoS(FileAttributes attributes)
{
ReplicaState state = POOL_POLICY.getTargetState(attributes);
boolean isSticky = POOL_POLICY.getStickyRecords(attributes).stream()
.anyMatch(StickyRecord::isNonExpiring);
if (state == ReplicaState.PRECIOUS) {
return isSticky ? QosManagement.DISK_TAPE : QosManagement.TAPE;
} else {
return isSticky ? QosManagement.DISK : QosManagement.VOLATILE;
}
}

/**
* <p>Map returned attributes to JsonFileAttributes object.</p>
*
Expand Down
Expand Up @@ -30,7 +30,7 @@ public boolean isValidAt(long time)
return isNonExpiring() || _expire > time;
}

private boolean isNonExpiring()
public boolean isNonExpiring()
{
return _expire == NON_EXPIRING;
}
Expand Down

0 comments on commit d47ab2b

Please sign in to comment.