/*
* Sandboxes.java
*
* Copyright (C) 2015 Pixelgaffer
*
* This work 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 of the License, or any later
* version.
*
* This work 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 version 2 and version 3 of the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.pixelgaffer.turnierserver.worker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.pixelgaffer.turnierserver.Airbrake;
import org.pixelgaffer.turnierserver.networking.messages.SandboxCommand;
import static org.pixelgaffer.turnierserver.PropertyUtils.*;
/**
* Diese Klasse speichert alle verbundenen Sandboxen.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Sandboxes
{
private static final List<Sandbox> sandboxes = new ArrayList<>();
public static final Map<UUID, Sandbox> sandboxJobs = new HashMap<>();
private static final Set<Integer> isolateBoxids = new HashSet<>();
private static final Map<UUID, Integer> jobBoxids = new HashMap<>();
private static final Random rnd = new Random();
private static int isolateMin = -1, isolateMax = -1;
/** Gibt eine freie Boxid für isolate zurück. */
public static int nextIsolateBoxid (UUID uuid)
{
WorkerMain.getLogger().todo("Soll diese Methode blockieren?");
if (isolateMin == -1)
isolateMin = getInt("isolate.id.min", 0);
if (isolateMax == -1)
isolateMax = getInt("isolate.id.max", 99);
while (true)
{
int boxid = rnd.nextInt(isolateMax - isolateMin) + isolateMin;
WorkerMain.getLogger().info("Next isolate id: " + boxid + " (<= " + isolateMin + " >= " + isolateMax + ")");
synchronized (isolateBoxids)
{
if (!isolateBoxids.contains(boxid))
{
isolateBoxids.add(boxid);
jobBoxids.put(uuid, boxid);
return boxid;
}
}
}
}
/** Markiert die zum Job gehörende Boxid von isolate als verfügbar. */
public static void releaseIsolateBoxid (@NonNull UUID uuid)
{
synchronized (isolateBoxids)
{
if (!jobBoxids.containsKey(uuid))
{
WorkerMain.getLogger().warning("Trying to release isolate boxid of unknown job " + uuid);
return;
}
int boxid = jobBoxids.get(uuid);
WorkerMain.getLogger().info("Release isolate id " + boxid);
isolateBoxids.remove(boxid);
jobBoxids.remove(uuid);
}
}
/**
* Fügt die Sandbox zur Liste hinzu.
*/
public static boolean addSandbox (Sandbox sandbox)
{
boolean success;
synchronized (sandboxes)
{
success = sandboxes.add(sandbox);
}
WorkerMain.workerInfo.getSandboxes().add(sandbox.getSandboxInfo());
try
{
WorkerMain.notifyInfoUpdated();
}
catch (IOException e)
{
Airbrake.log(e).printStackTrace();
}
return success;
}
/**
* Entfernt die Sandbox aus der Liste. Ruft außerdem
* {@link Sandbox#disconnected()} auf.
*/
public static boolean removeSandbox (Sandbox sandbox)
{
WorkerMain.getLogger().info("Die Sandbox " + sandbox + " hat sich disconnected");
sandbox.disconnected();
boolean success;
synchronized (sandboxes)
{
success = sandboxes.remove(sandbox);
}
WorkerMain.workerInfo.getSandboxes().remove(sandbox.getSandboxInfo());
try
{
WorkerMain.notifyInfoUpdated();
}
catch (IOException e)
{
Airbrake.log(e).printStackTrace();
}
return success;
}
/**
* Schickt den Job an eine Sandbox und gibt diese zurück. Wenn keine Sandbox
* unbeschäftigt ist, wird null zurückgegeben. DIESE METHODE WARTET NICHT
* AUF EINE FREIE SANDBOX!
*/
public static Sandbox send (SandboxCommand job) throws IOException
{
synchronized (sandboxes)
{
for (Sandbox s : sandboxes)
{
if (s.getLangs().contains(job.getLang()) && !s.isBusy())
{
if (s.sendJob(job))
return s;
}
}
}
return null;
}
}