/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.jenkins.results.parser; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.TreeMap; import org.json.JSONArray; import org.json.JSONObject; /** * @author Peter Yoo */ public class JenkinsMaster implements Comparable<JenkinsMaster> { public JenkinsMaster(String masterName, String masterURL) { _masterName = masterName; _masterURL = masterURL; } public synchronized void addRecentBatch(int batchSize) { _batchSizes.put( System.currentTimeMillis() + maxRecentBatchAge, batchSize); getAvailableSlavesCount(); } @Override public int compareTo(JenkinsMaster jenkinsMaster) { Integer availableSlavesCount = getAvailableSlavesCount(); int value = availableSlavesCount.compareTo( jenkinsMaster.getAvailableSlavesCount()); if (value != 0) { return -value; } Random random = new Random(); while (true) { int result = random.nextInt(3) - 1; if (result != 0) { return result; } } } public int getAvailableSlavesCount() { int recentBatchSizesTotal = _getRecentBatchSizesTotal(); StringBuilder sb = new StringBuilder(); sb.append("{availableSlavesCount="); int availableSlavesCount = _reportedAvailableSlavesCount - recentBatchSizesTotal; sb.append(availableSlavesCount); sb.append(", masterURL="); sb.append(_masterURL); sb.append(", recentBatchSizesTotal="); sb.append(recentBatchSizesTotal); sb.append(", reportedAvailableSlavesCount="); sb.append(_reportedAvailableSlavesCount); sb.append("}"); _summary = sb.toString(); return availableSlavesCount; } public String getMasterName() { return _masterName; } public boolean isAvailable() { return _available; } @Override public String toString() { getAvailableSlavesCount(); return _summary; } public void update() { JSONObject computerJSONObject = null; JSONObject queueJSONObject = null; try { computerJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL( JenkinsResultsParserUtil.combine( _masterURL, "/computer/api/json?tree=computer[displayName,", "idle,offline]")), false, 5000); queueJSONObject = JenkinsResultsParserUtil.toJSONObject( JenkinsResultsParserUtil.getLocalURL( _masterURL + "/queue/api/json?tree=items[task[name],why]"), false, 5000); } catch (Exception e) { System.out.println("Unable to read " + _masterURL); _available = false; return; } _available = true; int idleCount = 0; JSONArray computerJSONArray = computerJSONObject.getJSONArray( "computer"); for (int i = 0; i < computerJSONArray.length(); i++) { JSONObject curComputerJSONObject = computerJSONArray.getJSONObject( i); if (curComputerJSONObject.getBoolean("idle") && !curComputerJSONObject.getBoolean("offline")) { String displayName = curComputerJSONObject.getString( "displayName"); if (!displayName.equals("master")) { idleCount++; } } } int queueCount = 0; if (queueJSONObject.has("items")) { JSONArray itemsJSONArray = queueJSONObject.getJSONArray("items"); for (int i = 0; i < itemsJSONArray.length(); i++) { JSONObject itemJSONObject = itemsJSONArray.getJSONObject(i); if (itemJSONObject.has("task")) { JSONObject taskJSONObject = itemJSONObject.getJSONObject( "task"); String taskName = taskJSONObject.getString("name"); if (taskName.equals("verification-node")) { continue; } } if (itemJSONObject.has("why")) { String why = itemJSONObject.getString("why"); if (why.endsWith("is offline")) { continue; } } queueCount++; } } _reportedAvailableSlavesCount = idleCount - queueCount; getAvailableSlavesCount(); } protected static long maxRecentBatchAge = 120 * 1000; private synchronized int _getRecentBatchSizesTotal() { long currentTimestamp = System.currentTimeMillis(); int recentBatchSizesTotal = 0; List<Long> expiredTimestamps = new ArrayList<>(_batchSizes.size()); for (long expirationTimestamp : _batchSizes.keySet()) { if (expirationTimestamp < currentTimestamp) { expiredTimestamps.add(expirationTimestamp); continue; } recentBatchSizesTotal += _batchSizes.get(expirationTimestamp); } for (Long expiredTimestamp : expiredTimestamps) { _batchSizes.remove(expiredTimestamp); } return recentBatchSizesTotal; } private boolean _available; private final Map<Long, Integer> _batchSizes = new TreeMap<>(); private final String _masterName; private final String _masterURL; private int _reportedAvailableSlavesCount; private String _summary; }