Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

-Added getResourcePoolEntryImproved which is an improved version of g…

…etResourcepoolEntry that moves some processing down to SQL

-Related modifications
(cherry picked from commit 3189e9bce71b9ce3883700a50ed9b57eba1bfd8c)
  • Loading branch information...
commit 47d74c8471149b2898baa4aba2300bf19ffb6195 1 parent e4b37fd
@pauloricardomg pauloricardomg authored timf committed
View
8 service/service/java/source/share/lib/workspace_service_derby_schema.sql
@@ -165,13 +165,17 @@ resourcepool VARCHAR(128) NOT NULL PRIMARY KEY,
file_time BIGINT NOT NULL
);
+-- using REAL for memory attributs to allow
+-- real division operations in ORDER BY statements
+
CREATE TABLE resourcepool_entries
(
resourcepool VARCHAR(128) NOT NULL,
hostname VARCHAR(128) NOT NULL,
associations VARCHAR(512) NOT NULL,
-maximum_memory INT,
-available_memory INT
+maximum_memory REAL,
+available_memory REAL,
+PRIMARY KEY(resourcepool, hostname)
);
--
View
20 service/service/java/source/src/org/globus/workspace/persistence/PersistenceAdapter.java
@@ -16,17 +16,18 @@
package org.globus.workspace.persistence;
+import java.util.Calendar;
+import java.util.Hashtable;
+import java.util.List;
+
import org.globus.workspace.network.AssociationEntry;
import org.globus.workspace.scheduler.defaults.ResourcepoolEntry;
-import org.globus.workspace.service.InstanceResource;
-import org.globus.workspace.service.GroupResource;
import org.globus.workspace.service.CoschedResource;
+import org.globus.workspace.service.GroupResource;
+import org.globus.workspace.service.InstanceResource;
import org.globus.workspace.service.binding.vm.CustomizationNeed;
import org.nimbustools.api.services.rm.DoesNotExistException;
-import java.util.Calendar;
-import java.util.Hashtable;
-
/**
* TODO: each module implementation needs to encapsulate its own persistence,
* the persistence package will go away entirely
@@ -153,8 +154,7 @@ public void replaceResourcepools(Hashtable resourcepools)
throws WorkspaceDatabaseException;
- public void replaceResourcepoolEntry(String name,
- ResourcepoolEntry entry)
+ public void replaceResourcepoolEntry(ResourcepoolEntry entry)
throws WorkspaceDatabaseException;
@@ -189,5 +189,11 @@ public void updatePropagationCounter(int n)
public void updateCursorPosition(long currentPosition)
throws WorkspaceDatabaseException;
+
+ //SQL processing
+
+ public List<ResourcepoolEntry> getAvailableEntriesSortedByFreeMemoryPercentage(int requestedMem)
+
+ throws WorkspaceDatabaseException;
}
View
6 service/service/java/source/src/org/globus/workspace/persistence/PersistenceAdapterConstants.java
@@ -177,6 +177,9 @@
public static final String SQL_SELECT_ALL_VMS_BY_OWNER =
"SELECT id FROM resources WHERE creator_dn=?";
+
+ public static final String SQL_SELECT_AVAILABLE_ENTRIES =
+ "SELECT * FROM resourcepool_entries WHERE available_memory >= ? ORDER BY (available_memory/maximum_memory) ASC";
public static final String[] PREPARED_STATEMENTS = {
SQL_SELECT_RESOURCES,
@@ -221,5 +224,6 @@
SQL_JOIN_SELECT_RESOURCE_POOL_MEMORY,
SQL_SELECT_ALL_VMS_IN_GROUP,
SQL_SELECT_ALL_VMS_IN_ENSEMBLE,
- SQL_SELECT_ALL_VMS_BY_OWNER};
+ SQL_SELECT_ALL_VMS_BY_OWNER,
+ SQL_SELECT_AVAILABLE_ENTRIES};
}
View
122 service/service/java/source/src/org/globus/workspace/persistence/PersistenceAdapterImpl.java
@@ -16,10 +16,23 @@
package org.globus.workspace.persistence;
+import java.io.IOException;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.sql.DataSource;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.nimbustools.api.services.rm.DoesNotExistException;
-import org.nimbustools.api.services.rm.ManageException;
import org.globus.workspace.Lager;
import org.globus.workspace.WorkspaceConstants;
import org.globus.workspace.network.Association;
@@ -30,25 +43,14 @@
import org.globus.workspace.persistence.impls.VirtualMachinePersistenceUtil;
import org.globus.workspace.scheduler.defaults.Resourcepool;
import org.globus.workspace.scheduler.defaults.ResourcepoolEntry;
-import org.globus.workspace.service.InstanceResource;
import org.globus.workspace.service.CoschedResource;
import org.globus.workspace.service.GroupResource;
+import org.globus.workspace.service.InstanceResource;
import org.globus.workspace.service.binding.vm.CustomizationNeed;
import org.globus.workspace.service.binding.vm.VirtualMachine;
import org.globus.workspace.service.binding.vm.VirtualMachinePartition;
-
-import javax.sql.DataSource;
-import java.io.IOException;
-import java.sql.Blob;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Hashtable;
+import org.nimbustools.api.services.rm.DoesNotExistException;
+import org.nimbustools.api.services.rm.ManageException;
public class PersistenceAdapterImpl implements WorkspaceConstants,
PersistenceAdapterConstants,
@@ -1879,7 +1881,7 @@ public void replaceResourcepools(Hashtable pools)
* @param name name
* @param entry pool entry
*/
- public void replaceResourcepoolEntry(String name, ResourcepoolEntry entry)
+ public void replaceResourcepoolEntry(ResourcepoolEntry entry)
throws WorkspaceDatabaseException {
if (this.dbTrace) {
@@ -1891,12 +1893,13 @@ public void replaceResourcepoolEntry(String name, ResourcepoolEntry entry)
try {
c = getConnection();
pstmt = ResourcepoolPersistenceUtil.
- updateAvailableMemory(name, entry, c);
+ updateAvailableMemory(entry.getResourcePool(), entry, c);
final int updated = pstmt.executeUpdate();
- if (updated == 0) {
+ if(updated == 1){
+ this.resourcepools = null; //clean cache
+ } else {
throw new WorkspaceDatabaseException("expected row update");
}
-
} catch(SQLException e) {
logger.error("",e);
throw new WorkspaceDatabaseException(e);
@@ -1972,7 +1975,8 @@ public synchronized Hashtable currentResourcepools(boolean cachedIsFine)
continue;
}
ResourcepoolEntry entry =
- new ResourcepoolEntry(hostname,
+ new ResourcepoolEntry(name,
+ hostname,
rs2.getInt(4),
rs2.getInt(5),
assocs);
@@ -1990,10 +1994,11 @@ public synchronized Hashtable currentResourcepools(boolean cachedIsFine)
} while (rs.next());
- rs = null;
- rs2 = null;
- pstmt = null;
- pstmt2 = null;
+ // rs = null;
+ // rs2 = null;
+ // pstmt = null;
+ // pstmt2 = null;
+ // is that needed? (in finally they're closed)
this.resourcepools = pools;
@@ -2285,5 +2290,72 @@ private int readCounter(int n, String prepd)
}
}
}
+
+ @Override
+ public List<ResourcepoolEntry> getAvailableEntriesSortedByFreeMemoryPercentage(int requestedMem) throws WorkspaceDatabaseException{
+
+ Connection c = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+
+ ArrayList<ResourcepoolEntry> entries = new ArrayList<ResourcepoolEntry>();
+
+ try {
+ c = getConnection();
+ pstmt = c.prepareStatement(SQL_SELECT_AVAILABLE_ENTRIES);
+ pstmt.setInt(1, requestedMem);
+ rs = pstmt.executeQuery();
+
+ if (rs == null || !rs.next()) {
+ if (lager.traceLog) {
+ logger.debug("no available resource pool entries");
+ }
+ } else do {
+ // rs was next'd above already
+ String name = rs.getString(1);
+ String hostname = rs.getString(2);
+ String assocs = rs.getString(3);
+
+ if (hostname == null) {
+ logger.error("hostname cannot be null for resource pool entry");
+ continue;
+ }
+
+ if (assocs == null) {
+ logger.error("assocs cannot be null for resource pool entry");
+ continue;
+ }
+
+ ResourcepoolEntry entry =
+ new ResourcepoolEntry(name,
+ hostname,
+ rs.getInt(4),
+ rs.getInt(5),
+ assocs);
+ entries.add(entry);
+
+ } while (rs.next());
+
+ return entries;
+
+ } catch(SQLException e) {
+ logger.error("",e);
+ throw new WorkspaceDatabaseException(e);
+ } finally {
+ try {
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ if (rs != null) {
+ rs.close();
+ }
+ if (c != null) {
+ returnConnection(c);
+ }
+ } catch (SQLException sql) {
+ logger.error("SQLException in finally cleanup", sql);
+ }
+ }
+ }
}
View
3  service/service/java/source/src/org/globus/workspace/scheduler/defaults/DefaultSlotManagement.java
@@ -304,9 +304,8 @@ public synchronized Reservation reserveCoscheduledSpace(
for (int i = 0; i < vmids.length; i++) {
- // no distinction between resource pools yet, use "any" (null)
try {
- nodes[i] = ResourcepoolUtil.getResourcepoolEntry(memory,
+ nodes[i] = ResourcepoolUtil.getResourcePoolEntryImproved(memory,
assocs,
this.db,
this.lager,
View
15 service/service/java/source/src/org/globus/workspace/scheduler/defaults/ResourcepoolEntry.java
@@ -18,13 +18,15 @@
public class ResourcepoolEntry {
+ private String resourcePool;
private String hostname;
private int memMax = -1; // in MBytes
private int memCurrent = -1; // in MBytes
private String supportedAssociations;
- public ResourcepoolEntry(String hostname, int memMax,
+ public ResourcepoolEntry(String resourcePool, String hostname, int memMax,
int memCurrent, String sa) {
+ this.resourcePool = resourcePool;
this.hostname = hostname;
this.memMax = memMax;
this.memCurrent = memCurrent;
@@ -91,8 +93,17 @@ public String toString() {
"hostname='" + this.hostname + '\'' +
", memMax=" + this.memMax +
", memCurrent=" + this.memCurrent +
- ", supportedNetworks='" + this.supportedAssociations + '\'' +
+ ", supportedNetworks='" + this.supportedAssociations +
+ ", percentEmpty= " + this.percentEmpty() + '\'' +
'}';
}
+ public void setResourcePool(String resourcePool) {
+ this.resourcePool = resourcePool;
+ }
+
+ public String getResourcePool() {
+ return resourcePool;
+ }
+
}
View
179 service/service/java/source/src/org/globus/workspace/scheduler/defaults/ResourcepoolUtil.java
@@ -117,7 +117,7 @@ static String getResourcepoolEntry(int mem,
if (entry != null) {
entry.addMemCurrent(-mem);
- db.replaceResourcepoolEntry(name, entry);
+ db.replaceResourcepoolEntry(entry);
if (eventLog) {
logger.info(Lager.ev(vmid) + "'" + name +
@@ -150,30 +150,7 @@ private static ResourcepoolEntry nextEntry(String name,
}
if (trace) {
-
- final StringBuilder buf =
- new StringBuilder("Looking for resource. Name = ");
-
- buf.append(name)
- .append(", mem = ")
- .append(mem);
-
- if (greedy) {
- buf.append(", greedy selection strategy");
- } else {
- buf.append(", round robin selection strategy");
- }
-
- buf.append(", needed networks: ");
- if (neededAssociations == null) {
- buf.append("null");
- } else {
- for (String neededAssociation : neededAssociations) {
- buf.append(neededAssociation).append(' ');
- }
- }
-
- logger.trace(buf.toString());
+ traceLookingForResource(mem, neededAssociations, greedy);
}
final List<ResourcepoolEntry> okNodes = memFilter(resourcepool, mem);
@@ -191,11 +168,7 @@ private static ResourcepoolEntry nextEntry(String name,
Collections.sort(okNodes, PERCENT_AVAILABLE);
if (trace) {
- for (ResourcepoolEntry okNode : okNodes) {
- logger.trace("available host: " + okNode.getHostname() +
- ", mem: " + okNode.getMemCurrent() +
- ", percent available: " + okNode.percentEmpty());
- }
+ traceAvailableEntries(okNodes);
}
if (greedy) {
@@ -357,6 +330,127 @@ private static void netFilter(List<ResourcepoolEntry> okNodes,
}
}
+
+ /**
+ * Note: Locking is assumed to be implemented above.
+ *
+ * @param mem needed memory
+ * @param neededAssociations array of needed associations, can be null
+ * @param db db
+ * @param lager logging switches
+ * @param vmid for logging
+ * @param greedy true if VMs should stack up on VMMs first, false if round robin
+ * @param preemptable indicates if the space can be pre-empted by higher priority reservations
+ * @return node name can not be null
+ * @throws ResourceRequestDeniedException exc
+ * @throws WorkspaceDatabaseException exc
+ */
+ static String getResourcePoolEntryImproved(int mem,
+ String[] neededAssociations,
+ final PersistenceAdapter db,
+ Lager lager,
+ int vmid,
+ boolean greedy)
+ throws ResourceRequestDeniedException,
+ WorkspaceDatabaseException {
+
+ if (db == null) {
+ throw new IllegalArgumentException("null persistence adapter");
+ }
+ if (lager == null) {
+ throw new IllegalArgumentException("lager may not be null");
+ }
+
+ final boolean eventLog = lager.eventLog;
+ final boolean trace = lager.traceLog;
+
+ if (trace) {
+ traceLookingForResource(mem, neededAssociations, greedy);
+ }
+
+ //availableEntries is never empty
+ final List<ResourcepoolEntry> availableEntries = getAvailableEntries(mem, neededAssociations, db, trace);
+
+ if (trace) {
+ traceAvailableEntries(availableEntries);
+ }
+
+ ResourcepoolEntry entry;
+ if (greedy) {
+ entry = randomLeastSpace(availableEntries, trace);
+ } else {
+ entry = randomMostSpace(availableEntries, trace);
+ }
+
+ entry.addMemCurrent(-mem);
+ db.replaceResourcepoolEntry(entry);
+
+ if (eventLog) {
+ logger.info(Lager.ev(vmid) + "'" + entry.getResourcePool() +
+ "' resource pool entry '" + entry.getHostname() +
+ "': " + mem + " MB reserved, " +
+ entry.getMemCurrent() + " MB left");
+ }
+
+ return entry.getHostname();
+
+ }
+
+ private static List<ResourcepoolEntry> getAvailableEntries(int mem,
+ String[] neededAssociations, final PersistenceAdapter db,
+ final boolean trace) throws WorkspaceDatabaseException,
+ ResourceRequestDeniedException {
+
+ final List<ResourcepoolEntry> availableEntries = db.getAvailableEntriesSortedByFreeMemoryPercentage(mem);
+
+ if(availableEntries.isEmpty()){
+ String err = "No resource pool with available memory for this request.";
+ logger.error(err);
+ throw new ResourceRequestDeniedException(err);
+ }
+
+ netFilter(availableEntries, neededAssociations, trace);
+
+ if(availableEntries.isEmpty()){
+ String err = "No resource pool with requested network associations.";
+ logger.error(err);
+ throw new ResourceRequestDeniedException(err);
+ }
+
+ return availableEntries;
+ }
+
+ private static void traceAvailableEntries(final List<ResourcepoolEntry> availableEntries) {
+ for (ResourcepoolEntry okNode : availableEntries) {
+ logger.trace("available host: " + okNode.getHostname() +
+ ", mem: " + okNode.getMemCurrent() +
+ ", percent available: " + okNode.percentEmpty());
+ }
+ }
+
+ private static void traceLookingForResource(int mem, String[] neededAssociations, boolean greedy) {
+ final StringBuilder buf =
+ new StringBuilder("Looking for resource. Mem = ");
+
+ buf.append(mem);
+
+ if (greedy) {
+ buf.append(", greedy selection strategy");
+ } else {
+ buf.append(", round robin selection strategy");
+ }
+
+ buf.append(", needed networks: ");
+ if (neededAssociations == null) {
+ buf.append("null");
+ } else {
+ for (String neededAssociation : neededAssociations) {
+ buf.append(neededAssociation).append(' ');
+ }
+ }
+
+ logger.trace(buf.toString());
+ }
/**
* NOTE: a node may not be in more than one resource pool, will
@@ -431,7 +525,7 @@ static void retireMem(String hostname,
entry.setMemCurrent(entry.getMemMax());
}
- db.replaceResourcepoolEntry(poolname, entry);
+ db.replaceResourcepoolEntry(entry);
returned = true;
@@ -490,6 +584,7 @@ static Hashtable loadResourcepools(String resourcepoolDirectory,
}
final File resourcepoolFile = new File(path);
+ String resourcePoolFileName = resourcepoolFile.getName();
if (!resourcepoolFile.isFile()) {
logger.warn("not a file: '" + path + "'");
@@ -497,9 +592,10 @@ static Hashtable loadResourcepools(String resourcepoolDirectory,
}
Resourcepool oldpool = null;
+
if (previous != null) {
oldpool = (Resourcepool)
- previous.get(resourcepoolFile.getName());
+ previous.get(resourcePoolFileName);
// skip reading if file modification time isn't newer than last
// container boot
@@ -507,10 +603,10 @@ static Hashtable loadResourcepools(String resourcepoolDirectory,
if (oldpool.getFileTime() ==
resourcepoolFile.lastModified()) {
logger.debug("file modification time for pool '"
- + resourcepoolFile.getName()
+ + resourcePoolFileName
+ "' is not newer, using old configuration");
- newPoolSet.put(resourcepoolFile.getName(),
+ newPoolSet.put(resourcePoolFileName,
oldpool);
continue;
}
@@ -533,7 +629,7 @@ static Hashtable loadResourcepools(String resourcepoolDirectory,
line = line.trim();
if (line.length() > 0) {
ResourcepoolEntry entry =
- getPoolEntry(line, oldpool);
+ getPoolEntry(resourcePoolFileName, line, oldpool);
if (entry != null) {
entries.put(entry.getHostname(), entry);
}
@@ -559,11 +655,11 @@ static Hashtable loadResourcepools(String resourcepoolDirectory,
resourcepool.setEntries(entries);
resourcepool.setFileTime(resourcepoolFile.lastModified());
- newPoolSet.put(resourcepoolFile.getName(), resourcepool);
+ newPoolSet.put(resourcePoolFileName, resourcepool);
if (traceLog) {
logger.debug("read in resourcepool " +
- resourcepoolFile.getName() + ": " +
+ resourcePoolFileName + ": " +
resourcepool);
}
}
@@ -662,10 +758,11 @@ private static void logChangedPool(String poolname,
}
}
- private static ResourcepoolEntry getPoolEntry(String line,
+ private static ResourcepoolEntry getPoolEntry(String resourcePool,
+ String line,
Resourcepool oldpool) {
- final ResourcepoolEntry entry = parseResourcepool(line);
+ final ResourcepoolEntry entry = parseResourcepool(resourcePool, line);
if (entry == null) {
return null;
}
@@ -734,7 +831,7 @@ private static ResourcepoolEntry getPoolEntry(String line,
return entry;
}
- private static ResourcepoolEntry parseResourcepool(String line) {
+ private static ResourcepoolEntry parseResourcepool(String resourcePool, String line) {
if (line == null) {
return null;
@@ -799,6 +896,6 @@ private static ResourcepoolEntry parseResourcepool(String line) {
return null;
}
- return new ResourcepoolEntry(hostname, mem, mem, sa);
+ return new ResourcepoolEntry(resourcePool, hostname, mem, mem, sa);
}
}
View
17 service/service/java/source/tests/org/globus/workspace/scheduler/defaults/ResourcepoolEntryTest.java
@@ -16,30 +16,33 @@
package org.globus.workspace.scheduler.defaults;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import org.globus.workspace.scheduler.defaults.ResourcepoolEntry;
import org.testng.annotations.Test;
-import static org.testng.Assert.*;
public class ResourcepoolEntryTest {
@Test
public void testPercentEmpty() {
- ResourcepoolEntry re = new ResourcepoolEntry("ahostname", 4096, 2048, "*");
+ ResourcepoolEntry re = new ResourcepoolEntry("aResourcePool", "ahostname", 4096, 2048, "*");
assertEquals(re.percentEmpty(), 50);
- re = new ResourcepoolEntry("ahostname", 4096, 1024, "*");
+ re = new ResourcepoolEntry("aResourcePool", "ahostname", 4096, 1024, "*");
assertEquals(re.percentEmpty(), 25);
- re = new ResourcepoolEntry("ahostname", 4096, 0, "*");
+ re = new ResourcepoolEntry("aResourcePool", "ahostname", 4096, 0, "*");
assertEquals(re.percentEmpty(), 0);
- re = new ResourcepoolEntry("ahostname", 4096, 1, "*");
+ re = new ResourcepoolEntry("aResourcePool", "ahostname", 4096, 1, "*");
if (re.percentEmpty() == 0) {
fail();
}
- re = new ResourcepoolEntry("ahostname", 4096, 4096, "*");
+ re = new ResourcepoolEntry("aResourcePool", "ahostname", 4096, 4096, "*");
assertEquals(re.percentEmpty(), 100);
}
@Test(expectedExceptions=IllegalStateException.class)
public void testPercentEmptyIllegal() {
- ResourcepoolEntry re = new ResourcepoolEntry("ahostname", 4096, 4097, "*");
+ ResourcepoolEntry re = new ResourcepoolEntry("aResourcePool", "ahostname", 4096, 4097, "*");
re.percentEmpty();
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.