package org.dcache.webadmin.view.pages.activetransfers;
import com.google.common.base.Strings;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Longs;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.extensions.model.AbstractCheckBoxModel;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.dcache.webadmin.controller.ActiveTransfersService;
import org.dcache.webadmin.controller.exceptions.ActiveTransfersServiceException;
import org.dcache.webadmin.view.beans.ActiveTransfersBean;
import org.dcache.webadmin.view.pages.basepage.BasePage;
import org.dcache.webadmin.view.util.CheckBoxColumn;
import org.dcache.webadmin.view.util.Role;
import static java.util.stream.Collectors.toList;
@SuppressWarnings("serial")
public class ActiveTransfersPage extends BasePage
{
private static final Logger _log = LoggerFactory.getLogger(ActiveTransfersPage.class);
private final Set<ActiveTransfersBean.Key> selected = new HashSet<>();
private final boolean isAdmin;
private String filter;
public ActiveTransfersPage()
{
isAdmin = getWebadminSession().hasAnyRole(new Roles(Role.ADMIN));
add(new FeedbackPanel("feedback"));
Form<?> filterForm = new Form<Void>("filterForm");
filterForm.add(new TextField<>("filter", new PropertyModel<String>(this, "filter")));
filterForm.add(new Button("clear") {
@Override
public void onSubmit()
{
filter = null;
}
});
filterForm.setDefaultButton(new Button("update"));
add(filterForm);
List<IColumn<ActiveTransfersBean, ColumnComparator>> columns = new ArrayList<>();
if (isAdmin) {
columns.add(new SelectColumn());
}
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("door"), ColumnComparator.DOOR, "cellName"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("domain"), ColumnComparator.DOMAIN, "domainName"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("id"), ColumnComparator.ID, "serialId"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("protocol"), ColumnComparator.PROTOCOL, "protocol"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("uid"), ColumnComparator.UID, "uid"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("gid"), ColumnComparator.GID, "gid"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("vomsGroup"), ColumnComparator.VOMSGROUP, "vomsGroup"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("process"), ColumnComparator.PROCESS, "process"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("pnfsid"), ColumnComparator.PNFSID, "pnfsId"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("pool"), ColumnComparator.POOL, "pool"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("host"), ColumnComparator.HOST, "replyHost"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("status"), ColumnComparator.STATUS, "sessionStatus"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("waiting"), ColumnComparator.SINCE, "timeWaiting"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("state"), ColumnComparator.STATE, "moverStatus"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("transferred"), ColumnComparator.TRANSFERRED, "bytesTransferred"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("throughput"), ColumnComparator.RATE, "transferRate"));
columns.add(new PropertyColumn<ActiveTransfersBean, ColumnComparator>(new ResourceModel("moverId"), ColumnComparator.JOB, "moverId"));
TransfersProvider provider = new TransfersProvider();
DataTable<ActiveTransfersBean, ColumnComparator> transfers = new DefaultDataTable<>("transfers", columns, provider, 1000);
Button submit = new Button("submit");
MetaDataRoleAuthorizationStrategy.authorize(submit, RENDER, Role.ADMIN);
Form<?> form = new Form<Void>("transfersForm") {
@Override
protected void onSubmit()
{
try {
getActiveTransfersService().kill(selected);
selected.clear();
} catch (ActiveTransfersServiceException e) {
_log.info("Failed to kill some movers: {}",
e.getMessage());
error(getStringResource("error.notAllMoversKilled"));
}
}
};
form.add(new TextField<>("filter", new PropertyModel<String>(this, "filter")));
form.add(transfers);
form.add(submit);
add(form);
addAutoRefreshToForm(form, 30, TimeUnit.SECONDS);
}
private ActiveTransfersService getActiveTransfersService()
{
return getWebadminApplication().getActiveTransfersService();
}
private class TransfersProvider extends SortableDataProvider<ActiveTransfersBean, ColumnComparator>
{
private static final long serialVersionUID = -8155360113018832985L;
private List<ActiveTransfersBean> transfers;
private List<ActiveTransfersBean> getTransfers()
{
if (transfers == null) {
transfers = new ArrayList<>(getActiveTransfersService().getTransfers());
}
if (!Strings.isNullOrEmpty(filter)) {
String s = filter.toLowerCase();
return transfers.stream()
.filter(transfer -> transfer.getCellName().toLowerCase().contains(s) ||
transfer.getDomainName().toLowerCase().contains(s) ||
transfer.getUid().toLowerCase().contains(s) ||
transfer.getGid().toLowerCase().contains(s) ||
transfer.getVomsGroup().toLowerCase().contains(s) ||
transfer.getPnfsId().toLowerCase().contains(s) ||
transfer.getPool().toLowerCase().contains(s) ||
transfer.getProcess().toLowerCase().contains(s) ||
transfer.getProtocol().toLowerCase().contains(s) ||
transfer.getReplyHost().toLowerCase().contains(s) ||
transfer.getMoverStatus().toLowerCase().contains(s) ||
transfer.getSessionStatus().toLowerCase().contains(s))
.collect(toList());
}
return transfers;
}
@Override
public void detach()
{
transfers = null;
}
@Override
public Iterator<? extends ActiveTransfersBean> iterator(long first, long count)
{
List<ActiveTransfersBean> data = getTransfers();
SortParam<ColumnComparator> sort = getSort();
if (sort != null) {
Comparator<ActiveTransfersBean> order = sort.getProperty();
if (order != null) {
if (!sort.isAscending()) {
order = Ordering.from(order).reverse();
}
Collections.sort(data, order);
}
}
return data.subList((int) first, (int) Math.min(first + count, data.size())).iterator();
}
@Override
public long size()
{
return getTransfers().size();
}
@Override
public IModel<ActiveTransfersBean> model(ActiveTransfersBean object)
{
return Model.of(object);
}
}
private enum ColumnComparator implements Comparator<ActiveTransfersBean>
{
DOOR {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getCellName().compareTo(o2.getCellName());
}
},
DOMAIN {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getDomainName().compareTo(o2.getDomainName());
}
},
ID {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return Longs.compare(o1.getSerialId(), o2.getSerialId());
}
},
PROTOCOL {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getProtocol().compareTo(o2.getProtocol());
}
},
UID {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getUid().compareTo(o2.getUid());
}
},
GID {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getGid().compareTo(o2.getGid());
}
},
VOMSGROUP {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getVomsGroup().compareTo(o2.getVomsGroup());
}
},
PROCESS {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getProcess().compareTo(o2.getProcess());
}
},
PNFSID {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getPnfsId().compareTo(o2.getPnfsId());
}
},
POOL {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getPool().compareTo(o2.getPool());
}
},
HOST {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getReplyHost().compareTo(o2.getReplyHost());
}
},
STATUS {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getSessionStatus().compareTo(o2.getSessionStatus());
}
},
SINCE {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return Longs.compare(o1.getWaitingSince(), o2.getWaitingSince());
}
},
STATE {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return o1.getMoverStatus().compareTo(o2.getMoverStatus());
}
},
TRANSFERRED {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return Longs.compare(o1.getBytesTransferred(), o2.getBytesTransferred());
}
},
RATE {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return Longs.compare(o1.getTransferRate(), o2.getTransferRate());
}
},
JOB {
@Override
public int compare(ActiveTransfersBean o1, ActiveTransfersBean o2)
{
return Longs.compare(o1.getMoverId(), o2.getMoverId());
}
}
}
private class SelectColumn extends CheckBoxColumn<ActiveTransfersBean, ColumnComparator>
{
public SelectColumn()
{
super(Model.of(""));
}
@Override
protected IModel<Boolean> newCheckBoxModel(
final IModel<ActiveTransfersBean> rowModel)
{
return new AbstractCheckBoxModel()
{
@Override
public boolean isSelected()
{
return selected.contains(rowModel.getObject().getKey());
}
@Override
public void unselect()
{
selected.remove(rowModel.getObject().getKey());
}
@Override
public void select()
{
selected.add(rowModel.getObject().getKey());
}
@Override
public void detach()
{
rowModel.detach();
}
};
}
}
}