/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive_grid_cloud_portal.cli.cmd.sched; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.ow2.proactive_grid_cloud_portal.cli.ApplicationContext; import org.ow2.proactive_grid_cloud_portal.cli.CLIException; import org.ow2.proactive_grid_cloud_portal.cli.RestConstants; import org.ow2.proactive_grid_cloud_portal.cli.cmd.AbstractCommand; import org.ow2.proactive_grid_cloud_portal.cli.cmd.AbstractIModeCommand; import org.ow2.proactive_grid_cloud_portal.cli.cmd.Command; import org.ow2.proactive_grid_cloud_portal.cli.utils.StringUtility; import org.ow2.proactive_grid_cloud_portal.scheduler.dto.RestMapPage; import org.ow2.proactive_grid_cloud_portal.scheduler.dto.UserJobData; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.NotConnectedRestException; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.PermissionRestException; public class ListJobCommand extends AbstractCommand implements Command { private String[] filterings; private boolean offsetFlag = false; private int offset = -1; private int beginIndex = 0; public ListJobCommand() { } public ListJobCommand(String... filtering) { this.filterings = filtering; processFilteringOps(); } @Override public void execute(ApplicationContext currentContext) throws CLIException { try { if (isIteractiveMode(currentContext)) { int numOfJobsPerPage = getNumOfJobsPerPage(currentContext); int numOfJobs = getNumberOfJobs(beginIndex, offset, currentContext); if (numOfJobs < numOfJobsPerPage) { printJobsList(beginIndex, numOfJobs, currentContext); } else { int pages = (numOfJobs / numOfJobsPerPage) + ((numOfJobs % numOfJobsPerPage) == 0 ? 0 : 1); int iterCount = 0; boolean hasQuit = false; // all pages except the last one for (; iterCount < pages - 1; iterCount++) { printJobsList(beginIndex + (iterCount * numOfJobsPerPage), numOfJobsPerPage, currentContext); String response = readLine(currentContext, "Page(%d/%d). Press ENTER to continue. 'q' to quit. ", (iterCount + 1), pages); if ("q".equalsIgnoreCase(response)) { hasQuit = true; break; } } if (!hasQuit) { // last page printJobsList(beginIndex + (iterCount * numOfJobsPerPage), numOfJobs - (iterCount * numOfJobsPerPage), currentContext); } } } else { printJobsList(beginIndex, (offsetFlag) ? offset : RestConstants.DFLT_PAGINATION_SIZE, currentContext); } } catch (Exception e) { handleError("An error occurred while retrieving job list:", e, currentContext); } } private void processFilteringOps() { if (filterings != null) { try { for (String nameValue : filterings) { if (nameValue.startsWith("latest=")) { setOffset(valueAsInt(nameValue)); } else if (nameValue.startsWith("from=")) { beginIndex = valueAsInt(nameValue); } else if (nameValue.startsWith("limit=")) { setOffset(valueAsInt(nameValue)); } } } catch (Exception e) { throw new IllegalArgumentException("Invalid filtering option(s).", e); } } } private void setOffset(int offset) { this.offset = offset; this.offsetFlag = true; } private static boolean isIteractiveMode(ApplicationContext currentContext) { return currentContext.getProperty(AbstractIModeCommand.IMODE, Boolean.TYPE) != null; } private static void printJobsList(int index, int offset, ApplicationContext currentContext) throws PermissionRestException, NotConnectedRestException, IOException { RestMapPage<Long, ArrayList<UserJobData>> page = currentContext.getRestClient() .getScheduler() .revisionAndJobsInfo(currentContext.getSessionId(), index, offset, false, true, true, true); Map<Long, ArrayList<UserJobData>> stateMap = page.getMap(); List<UserJobData> jobs = stateMap.values().iterator().next(); currentContext.getDevice().writeLine("%s", StringUtility.jobsAsString(jobs)); } private static int getNumberOfJobs(int index, int offset, ApplicationContext currentContext) throws NotConnectedRestException, PermissionRestException { return currentContext.getRestClient() .getScheduler() .jobs(currentContext.getSessionId(), index, offset) .getList() .size(); } private static Integer valueAsInt(String nameValue) { return Integer.valueOf(nameValue.split("=")[1]); } private static int getNumOfJobsPerPage(ApplicationContext currentContext) { int columns = currentContext.getDevice().getWidth(); int lines = currentContext.getDevice().getHeight(); int numOfJobsPerPage = 0; if (lines > 0) { if (columns < 81) { /* * 5 => 2 lines for table headers, 1 blank after, 1 for user * opt, 1 blank before 2 => requires two lines per job */ numOfJobsPerPage = (lines - 5) / 2; } else { /* * 4 => 1 lines for table headers, ... */ numOfJobsPerPage = lines - 4; } } if (numOfJobsPerPage < 1) { // if terminal height, width not available numOfJobsPerPage = RestConstants.DFLT_PAGINATION_SIZE; } return numOfJobsPerPage; } }