/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.jstestdriver; import org.joda.time.Instant; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; /** * @author jeremiele@google.com (Jeremie Lenfant-Engelmann) */ public class SlaveBrowser { private final Time time; private final String id; private final BrowserInfo browserInfo; private final BlockingQueue<Command> commandsToRun = new LinkedBlockingQueue<Command>(); private long timeout = 10; private TimeUnit timeUnit = TimeUnit.SECONDS; private Instant lastHeartBeat; private Set<FileInfo> fileSet = new LinkedHashSet<FileInfo>(); private final BlockingQueue<CommandResponse> responses = new LinkedBlockingQueue<CommandResponse>(); private Command commandRunning = null; private Command lastCommandDequeued; public SlaveBrowser(Time time, String id, BrowserInfo browserInfo) { this.time = time; lastHeartBeat = time.now(); this.id = id; this.browserInfo = browserInfo; } public String getId() { return id; } public static class CommandResponse { private final String response; private final boolean last; public CommandResponse(String response, boolean last) { this.response = response; this.last = last; } /** * @return the response */ public String getResponse() { return response; } /** * @return the isLast */ public boolean isLast() { return last; } } public void createCommand(String data) { try { commandsToRun.put(new Command(data)); } catch (InterruptedException e) { throw new RuntimeException(e); } } public synchronized Command dequeueCommand() { try { Command command = commandsToRun.poll(timeout, timeUnit); if (command != null) { commandRunning = command; lastCommandDequeued = command; } return command; } catch (InterruptedException e) { // The server was killed } return null; } public Command getLastDequeuedCommand() { return lastCommandDequeued; } public BrowserInfo getBrowserInfo() { return browserInfo; } public void setDequeueTimeout(long timeout, TimeUnit timeUnit) { this.timeout = timeout; this.timeUnit = timeUnit; } public void heartBeat() { lastHeartBeat = time.now(); } public Instant getLastHeartBeat() { return lastHeartBeat; } public void addFiles(Set<FileInfo> fileSet) { this.fileSet.removeAll(fileSet); this.fileSet.addAll(fileSet); } public Set<FileInfo> getFileSet() { return fileSet; } public void resetFileSet() { fileSet.clear(); } public CommandResponse getResponse() { try { return responses.take(); } catch (InterruptedException e) { return null; } } public void addResponse(String response, boolean isLast) { if (isLast) { commandRunning = null; } responses.offer(new CommandResponse(response, isLast)); } public void clearResponseQueue() { responses.clear(); } public boolean isCommandRunning() { return commandRunning != null; } public synchronized Command getCommandRunning() { return commandRunning; } public void removeFiles(Collection<String> errorFiles) { Set<FileInfo> filesInfoToRemove = new LinkedHashSet<FileInfo>(); for (String f : errorFiles) { for (FileInfo info : fileSet) { if (info.getFileName().equals(f)) { filesInfoToRemove.add(info); break; } } } fileSet.removeAll(filesInfoToRemove); } public Command peekCommand() { return commandsToRun.peek(); } public void clearCommandRunning() { if (commandRunning != null) { commandRunning = null; commandsToRun.clear(); responses.clear(); } } }