Commit: fa95ddb2e16f3cebacdd80e81f273bda7d06d375 Author: Matt Ficken <v-maf...@microsoft.com> Thu, 12 Sep 2013 15:17:58 -0700 Parents: 49a25d28ec9e8d6e7693392e2dba9e7effcfd903 Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=fa95ddb2e16f3cebacdd80e81f273bda7d06d375 Log: adding Host#getPfttConfDir and Host#getPfttCacheDir Former-commit-id: 6d76acfba8d1e52bb593921b396be3ef748866c4 Changed paths: M src/com/github/mattficken/io/ArrayUtil.java M src/com/mostc/pftt/host/AHost.java M src/com/mostc/pftt/host/CommonCommandManager.java M src/com/mostc/pftt/host/Host.java M src/com/mostc/pftt/host/LocalHost.java M src/com/mostc/pftt/host/RemoteHost.java M src/com/mostc/pftt/host/SSHHost.java M src/com/mostc/pftt/host/TempFileExecOutput.java M src/com/mostc/pftt/model/custom/NTFSACL.java M src/com/mostc/pftt/scenario/EnchantScenario.java M src/com/mostc/pftt/scenario/OpcacheScenario.java M src/com/mostc/pftt/scenario/SMBCAScenario.java M src/com/mostc/pftt/scenario/SMBDFSScenario.java M src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java M src/com/mostc/pftt/scenario/Scenario.java M src/com/mostc/pftt/scenario/ScenarioSet.java M src/com/mostc/pftt/scenario/ScenarioSetSetup.java M src/com/mostc/pftt/scenario/WinCacheUScenario.java M src/com/mostc/pftt/scenario/XDebugProfilingScenario.java M src/com/mostc/pftt/scenario/app/JoomlaScenario.groovy M src/com/mostc/pftt/util/HostEnvUtil.java M src/com/mostc/pftt/util/WinDebugManager.java
diff --git a/src/com/github/mattficken/io/ArrayUtil.java b/src/com/github/mattficken/io/ArrayUtil.java index 8a4d692..7838186 100644 --- a/src/com/github/mattficken/io/ArrayUtil.java +++ b/src/com/github/mattficken/io/ArrayUtil.java @@ -135,6 +135,8 @@ public class ArrayUtil { } public static <E extends Object> List<E> toList(E[] e) { + if (e==null) + return new ArrayList<E>(0); // TODO temp ArrayList<E> o = new ArrayList<E>(e.length); for ( int i=0 ; i < e.length ; i++ ) o.add(e[i]); diff --git a/src/com/mostc/pftt/host/AHost.java b/src/com/mostc/pftt/host/AHost.java index 6e2fd4f..f84b37f 100644 --- a/src/com/mostc/pftt/host/AHost.java +++ b/src/com/mostc/pftt/host/AHost.java @@ -284,6 +284,7 @@ public abstract class AHost extends Host implements IProgramRunner { return isWindows() ? getPhpSdkDir() + "\\PFTT\\Current\\" : getPhpSdkDir() + "/PFTT/current/"; } } + @Override public String getPhpSdkDir() { if (StringUtil.isNotEmpty(php_sdk_dir)) @@ -671,14 +672,14 @@ public abstract class AHost extends Host implements IProgramRunner { private boolean reported_7zip_already_installed = false; private static void install7Zip(ConsoleManager cm, AHost src_host, AHost dst_host) throws Exception { - final String src_7z_path = src_host.getPfttDir()+"\\bin\\7za.exe"; + final String src_7z_path = src_host.getPfttBinDir()+"\\7za.exe"; if (!src_host.exists(src_7z_path)) { if (cm!=null) cm.println(EPrintType.WARNING, "install7Zip", "7za.exe not found on source: "+src_host); return; } - final String dst_7z_path = dst_host.getPfttDir()+"\\bin\\7za.exe"; + final String dst_7z_path = dst_host.getPfttBinDir()+"\\7za.exe"; if (dst_host.exists(dst_7z_path) && src_host.getSize(src_7z_path)==dst_host.getSize(dst_7z_path)) { if (dst_host.reported_7zip_already_installed) @@ -721,7 +722,7 @@ public abstract class AHost extends Host implements IProgramRunner { if (cm!=null) cm.println(EPrintType.IN_PROGRESS, getClass(), "decompress output_dir="+output_dir+" zip7_file="+zip7_file); - String cmd = silenceCmd(getPfttDir()+"\\bin\\7za x -mx=9 -mmt="+getCPUCount()+" -bd -y -o"+output_dir+" "+zip7_file); + String cmd = silenceCmd(getPfttBinDir()+"\\7za x -mx=9 -mmt="+getCPUCount()+" -bd -y -o"+output_dir+" "+zip7_file); return exec(cmd, AHost.ONE_HOUR); } @@ -748,7 +749,7 @@ public abstract class AHost extends Host implements IProgramRunner { // x=9 => highest compression // mt=[cpus] => use several threads == number of cpus => maximizes speed // bd => no progress bar - final String cmd = silenceCmd(getPfttDir()+"\\bin\\7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on -mmt="+getCPUCount()+" -bd "+zip7_file+" "+src); + final String cmd = silenceCmd(getPfttBinDir()+"\\7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on -mmt="+getCPUCount()+" -bd "+zip7_file+" "+src); if (cm!=null) cm.println(EPrintType.IN_PROGRESS, getClass(), "compress zip7_file="+zip7_file+" src="+src); @@ -1136,5 +1137,6 @@ public abstract class AHost extends Host implements IProgramRunner { } protected abstract boolean deleteSingleFile(String path); + public abstract boolean isBusy(); } // end public abstract class AHost diff --git a/src/com/mostc/pftt/host/CommonCommandManager.java b/src/com/mostc/pftt/host/CommonCommandManager.java index 1c191b8..270e082 100644 --- a/src/com/mostc/pftt/host/CommonCommandManager.java +++ b/src/com/mostc/pftt/host/CommonCommandManager.java @@ -21,7 +21,7 @@ public class CommonCommandManager { win_close_all_handles_lock.tryLock(10, TimeUnit.SECONDS); } catch ( InterruptedException ex ) {} try { - handle_out = host.execOut(host.getPfttDir()+"\\bin\\handle -accepteula -p "+process_id+" -a", 10); + handle_out = host.execOut(host.getPfttBinDir()+"\\handle -accepteula -p "+process_id+" -a", 10); } finally { try { win_close_all_handles_lock.unlock(); @@ -34,7 +34,7 @@ public class CommonCommandManager { String handle_type = h_part[1]; if (handle_id.endsWith(":") && handle_type.equalsIgnoreCase("File")) { handle_id = handle_id.substring(0, handle_id.length()-1); - String handle_cmd = host.getPfttDir()+"\\bin\\handle -accepteula -p "+process_id+" -y -c "+handle_id; + String handle_cmd = host.getPfttBinDir()+"\\handle -accepteula -p "+process_id+" -y -c "+handle_id; try { win_close_all_handles_lock.tryLock(10, TimeUnit.SECONDS); } catch ( InterruptedException ex ) {} @@ -70,7 +70,7 @@ public class CommonCommandManager { win_kill_process_lock.tryLock(5, TimeUnit.SECONDS); } catch ( InterruptedException ex ) {} try { - host.exec(host.getPfttDir()+"\\bin\\pskill -accepteula -t -p "+process_id, 20); + host.exec(host.getPfttBinDir()+"\\pskill -accepteula -t -p "+process_id, 20); //host.exec("TASKKILL /FI \"IMAGENAME eq "+image_name+"\" /FI \"PID eq "+process_id+"\" /F /T", 20); } finally { try { @@ -82,7 +82,7 @@ public class CommonCommandManager { win_kill_process_lock.tryLock(5, TimeUnit.SECONDS); } catch ( InterruptedException ex ) {} try { - host.exec(host.getPfttDir()+"\\bin\\pskill -accepteula -t -p "+process_id, 20); + host.exec(host.getPfttBinDir()+"\\pskill -accepteula -t -p "+process_id, 20); //host.exec("TASKKILL /FI \"IMAGENAME eq "+image_name+"\" /FI \"PID eq "+process_id+"\" /F /T", 20); } finally { try { diff --git a/src/com/mostc/pftt/host/Host.java b/src/com/mostc/pftt/host/Host.java index 1c91d64..45286f3 100644 --- a/src/com/mostc/pftt/host/Host.java +++ b/src/com/mostc/pftt/host/Host.java @@ -606,6 +606,16 @@ public abstract class Host { public abstract String getHomeDir(); public abstract String getPhpSdkDir(); public abstract String getPfttDir(); + + public String getPfttBinDir() { + return joinIntoOnePath(getPfttDir(), "bin"); + } + public String getPfttCacheDir() { + return joinIntoOnePath(getPfttDir(), "cache"); + } + public String getPfttConfDir() { + return joinIntoOnePath(getPfttDir(), "conf"); + } public String joinIntoOnePath(String ...parts) { if (parts==null||parts.length==0) diff --git a/src/com/mostc/pftt/host/LocalHost.java b/src/com/mostc/pftt/host/LocalHost.java index 2ce8ad8..4140526 100644 --- a/src/com/mostc/pftt/host/LocalHost.java +++ b/src/com/mostc/pftt/host/LocalHost.java @@ -25,6 +25,7 @@ import java.util.LinkedList; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Pattern; @@ -46,7 +47,9 @@ import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; import com.mostc.pftt.runner.AbstractTestPackRunner.TestPackRunnerThread; import com.mostc.pftt.util.TimerUtil; +import com.mostc.pftt.util.TimerUtil.ObjectRunnable; import com.mostc.pftt.util.TimerUtil.TimerThread; +import com.mostc.pftt.util.TimerUtil.WaitableRunnable; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinNT.HANDLE; @@ -55,7 +58,7 @@ import com.sun.jna.platform.win32.WinNT.HANDLE; * * LocalHost is fairly straightforward for Linux. * - * Windows has issues running large numbers of processes or large numbers of filesystem operations. LocalHost + * Windows has many issues running large numbers of processes or large numbers of filesystem operations. LocalHost * has several special internal mechanisms to try to contain and manage those issues so the rest of PFTT doesn't have to deal with them. * * @see SSHHost @@ -79,12 +82,47 @@ public class LocalHost extends AHost { } protected final CommonCommandManager ccm; // share some 'shelling out' code with SSHHost protected final HashMap<Thread,Object> close_thread_set; // for LocalExecHandle#close + protected static final AtomicInteger active_proc_counter = new AtomicInteger(); public LocalHost() { close_thread_set = new HashMap<Thread,Object>(); ccm = new CommonCommandManager(); } + public int getActiveProcessCount() { + return staticGetActiveProcessCount(); + } + + public int staticGetActiveProcessCount() { + return active_proc_counter.get(); + } + + protected static final AtomicInteger wait_runnable_thread_counter = new AtomicInteger(); + protected <E extends Object> E runWaitRunnable(String name_prefix, int seconds, final ObjectRunnable<E> r) throws Exception { + int a = wait_runnable_thread_counter.incrementAndGet(); + if (a > Math.max(600, getActiveProcessCount()*1.8)) { + int i=0; + do { + try { + i++; + Thread.sleep(50*i); + } catch (InterruptedException e) {} + } while (wait_runnable_thread_counter.get() > Math.max(400, getActiveProcessCount()*1.4) && i < 40); + } + WaitableRunnable<E> h; + try { + h = TimerUtil.runWaitSeconds(name_prefix, seconds, r); + } finally { + wait_runnable_thread_counter.decrementAndGet(); + } + if (h==null) + return null; + else if (h.getException()!=null) + throw h.getException(); + else + return h.getResult(); + } // end protected E runWaitRunnable + public static boolean isLocalhostWindows() { return is_windows; } @@ -119,13 +157,13 @@ public class LocalHost extends AHost { // // if (!checked_elevate) { - found_elevate = exists(getPfttDir()+"\\bin\\elevate.exe"); + found_elevate = exists(getPfttBinDir()+"\\elevate.exe"); checked_elevate = true; } if (found_elevate) { // execute command with this utility that will elevate the program using Windows UAC - cmd = getPfttDir() + "\\bin\\elevate "+cmd; + cmd = getPfttBinDir() + "\\elevate "+cmd; } } @@ -302,7 +340,7 @@ public class LocalHost extends AHost { this.stdin = stdin; this.stdout = stdout; this.stderr = stderr; - this.image_name = StringUtil.unquote(basename(cmd_array[0])); + this.image_name = cmd_array==null||cmd_array.length==0?"":StringUtil.unquote(basename(cmd_array[0])); if (isLocalhostWindows()) { if (this.image_name.endsWith(".cmd")) this.image_name = "cmd.exe"; // IMPORTANT: this is how its identified in the Windows process table @@ -316,6 +354,22 @@ public class LocalHost extends AHost { final Process p = this.process.get(); if (p==null) return false; + if (isWindows()) { + Boolean b = null; + try { + b = runWaitRunnable("IsRunning", 10, new ObjectRunnable<Boolean>() { + public Boolean run() { + return doIsRunning(p); + } + }); + } catch ( Exception ex ) {} + return b == null ? false : b.booleanValue(); + } else { + return doIsRunning(p); + } + } + + protected boolean doIsRunning(Process p) { try { p.exitValue(); return false; @@ -370,11 +424,7 @@ public class LocalHost extends AHost { for ( int tries = 0 ; tries < 10 ; tries++ ) { // // - try { - p.exitValue(); - break; - // process terminated, stop trying (or may terminate new process reusing the same id) - } catch ( Throwable t ) { + if (doIsRunning(p)) { if (stdout!=null) { try { stdout.close(); @@ -474,7 +524,10 @@ public class LocalHost extends AHost { t2.printStackTrace(); } // - } // end try + } else { + // process terminated, stop trying (or may terminate new process reusing the same id) + break; + } } // end for // by now process should be dead/should have stopped writing // so #exec_copy_lines should stop (which will stop blocking whatever called #exec_impl or #exec or #execOut) @@ -529,11 +582,31 @@ public class LocalHost extends AHost { // ignores STDERR // wait for process exit (shouldn't get here until exit or #close though) + final ObjectRunnable<Integer> or = isWindows() ? new ObjectRunnable<Integer>() { + public Integer run() { + try { + return p.exitValue(); + } catch ( Exception ex ) { + return null; + } + } + } : null; for (int time = 50;wait.get();) { - try { - exit_code = p.exitValue(); - break; - } catch ( IllegalThreadStateException ex ) {} + /*if (isWindows()) { + Integer e = null; + try { + e = runWaitRunnable("ExitValue", 10, or); + } catch ( Exception ex ) {} + if (e!=null) { + exit_code = e.intValue(); + break; + } // else: process is still running + } else {*/ + try { + exit_code = p.exitValue(); + break; + } catch ( IllegalThreadStateException ex ) {} + //} try { Thread.sleep(time); } catch ( InterruptedException ex ) { @@ -557,13 +630,24 @@ public class LocalHost extends AHost { } // + active_proc_counter.decrementAndGet(); + // free up process handle if (process.get()!=null) { // don't call #destroy on this process if #close already has // // on Windows, it can block forever try { - p.destroy(); + if (isWindows()) { + runWaitRunnable("Destroy", 60, new ObjectRunnable<Boolean>() { + public Boolean run() { + p.destroy(); + return true; + } + }); + } else { + p.destroy(); + } } catch ( Exception ex ) {} } @@ -677,9 +761,9 @@ public class LocalHost extends AHost { this.run(output_sb, charset, suspend_seconds); if (a!=null) - a.cancel(); + a.close(); if (b!=null) - b.cancel(); + b.close(); } @Override @@ -765,13 +849,7 @@ public class LocalHost extends AHost { return (String[])parts.toArray(new String[]{}); } // end public static String[] splitCmdString - static final UncaughtExceptionHandler IGNORE = new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread arg0, Throwable arg1) { - } - }; - @SuppressWarnings("deprecation") - protected Process guardStart(final ProcessBuilder builder) throws IOException, InterruptedException { + protected Process guardStart(final ProcessBuilder builder) throws Exception, InterruptedException { if (!isWindows()) return builder.start(); @@ -779,43 +857,14 @@ public class LocalHost extends AHost { // and sometimes CLI // // call ProcessBuilder#start in separate thread to monitor it - final AtomicReference<IOException> ex_ref = new AtomicReference<IOException>(); - final AtomicReference<Process> proc_ref = new AtomicReference<Process>(); - final Thread start_thread = new Thread() { - public void run() { - try { - proc_ref.set(builder.start()); - synchronized(proc_ref) { - proc_ref.notifyAll(); - } - } catch ( IOException ex ) { - ex_ref.set(ex); - } + return runWaitRunnable("ProcessBuilder", 120, new ObjectRunnable<Process>() { + public Process run() throws IOException { + return builder.start(); } - }; - start_thread.setUncaughtExceptionHandler(IGNORE); - start_thread.setDaemon(true); - start_thread.setName("ProcessBuilder"+start_thread.getName()); - start_thread.start(); - // wait up to 120 seconds for ProcessBuilder#start - try { - synchronized(proc_ref) { - proc_ref.wait(120000); - } - } catch ( Exception ex ) {} - Process proc = proc_ref.get(); - if (proc==null) { - // try to kill off the thread (ProcessBuilder#start is native code though) - start_thread.stop(new RuntimeException("ProcessBuilder#start timeout (Localhost)")); - - IOException ex = ex_ref.get(); - if (ex!=null) - throw ex; - } - return proc; + }); } // end protected Process guardStart - protected LocalExecHandle exec_impl(String[] cmd_array, Map<String,String> env, String chdir, byte[] stdin_data) throws IOException, InterruptedException { + protected LocalExecHandle exec_impl(String[] cmd_array, Map<String,String> env, String chdir, byte[] stdin_data) throws Exception, InterruptedException { Process process = null; { ProcessBuilder builder = new ProcessBuilder(cmd_array); @@ -880,6 +929,7 @@ public class LocalHost extends AHost { if (process==null) return new LocalExecHandle(process, null, null, null, null); + active_proc_counter.incrementAndGet(); OutputStream stdin = process.getOutputStream(); if (stdin_data!=null && stdin_data.length>0) { @@ -1177,5 +1227,13 @@ public class LocalHost extends AHost { // TODO Auto-generated method stub return false; } + + @Override + public boolean isBusy() { + // REMINDER: processes launched by cmd.exe on Windows automatically create + // a second process (conhost.exe) to manage the console + // so the actual number of processes will be doubled on Windows + return active_proc_counter.get() < (isWindows() ? 192 : 400 ); + } } // end public class Host diff --git a/src/com/mostc/pftt/host/RemoteHost.java b/src/com/mostc/pftt/host/RemoteHost.java index db4aeb6..c6a56ce 100644 --- a/src/com/mostc/pftt/host/RemoteHost.java +++ b/src/com/mostc/pftt/host/RemoteHost.java @@ -22,13 +22,13 @@ public abstract class RemoteHost extends AHost { public ExecOutput execElevatedOut(String cmd, int timeout_sec, Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, TestPackRunnerThread test_thread, int slow_timeout_sec) throws Exception { if (isWindows()) { if (!checked_elevate) { - found_elevate = exists(getPfttDir()+"\\bin\\elevate.exe"); + found_elevate = exists(getPfttBinDir()+"\\elevate.exe"); checked_elevate = true; } if (found_elevate) { // execute command with this utility that will elevate the program using Windows UAC - cmd = getPfttDir() + "\\bin\\elevate "+cmd; + cmd = getPfttBinDir() + "\\elevate "+cmd; } } diff --git a/src/com/mostc/pftt/host/SSHHost.java b/src/com/mostc/pftt/host/SSHHost.java index 3409d9c..5fe1288 100644 --- a/src/com/mostc/pftt/host/SSHHost.java +++ b/src/com/mostc/pftt/host/SSHHost.java @@ -869,4 +869,10 @@ public class SSHHost extends RemoteHost { return null; } + @Override + public boolean isBusy() { + // hard to check so don't check for now + return false; + } + } // end public class SSHHost diff --git a/src/com/mostc/pftt/host/TempFileExecOutput.java b/src/com/mostc/pftt/host/TempFileExecOutput.java index fdb3fea..7eea82c 100644 --- a/src/com/mostc/pftt/host/TempFileExecOutput.java +++ b/src/com/mostc/pftt/host/TempFileExecOutput.java @@ -14,8 +14,14 @@ public class TempFileExecOutput extends ExecOutput { this.output = eo.output; this.temp_file = temp_file; } + + public TempFileExecOutput cleanupSuccess(AHost host) { + if (isSuccess()) + cleanup(host); + return this; + } - public boolean cleanupIfSuccess(AHost host) { + public boolean cleanupIsSuccess(AHost host) { if (isSuccess()) { cleanup(host); return true; diff --git a/src/com/mostc/pftt/model/custom/NTFSACL.java b/src/com/mostc/pftt/model/custom/NTFSACL.java index f968d30..e21e678 100644 --- a/src/com/mostc/pftt/model/custom/NTFSACL.java +++ b/src/com/mostc/pftt/model/custom/NTFSACL.java @@ -586,7 +586,7 @@ public class NTFSACL { protected static void setACL(Host host, String args) throws Exception { //WL( '\t' + 'setacl' + args ); - host.exec(host.getPfttDir()+"/bin/setacl " + args, Host.FOUR_HOURS ); + host.exec(host.getPfttBinDir()+"/setacl " + args, Host.FOUR_HOURS ); } } // end public class NTFSACL diff --git a/src/com/mostc/pftt/scenario/EnchantScenario.java b/src/com/mostc/pftt/scenario/EnchantScenario.java index e995246..99be323 100644 --- a/src/com/mostc/pftt/scenario/EnchantScenario.java +++ b/src/com/mostc/pftt/scenario/EnchantScenario.java @@ -28,7 +28,7 @@ public class EnchantScenario extends INIScenario { // LATER php on non-windows may need a dictionary too ?? String dst = build.getBuildPath()+"/share/"; if (!host.exists(dst)) { - host.copyElevated(host.getPfttDir()+"/cache/util/enchant/share", dst); + host.copyElevated(host.getPfttCacheDir()+"/util/enchant/share", dst); // make sure libraries are where they need to be also @@ -63,7 +63,7 @@ public class EnchantScenario extends INIScenario { } public static String getDictionaryFile(AHost host) { - return host.getPfttDir()+"/cache/util/enchant/share/myspell/dicts/en_US.dic"; + return host.getPfttCacheDir()+"/util/enchant/share/myspell/dicts/en_US.dic"; } } // end public class EnchantScenario diff --git a/src/com/mostc/pftt/scenario/OpcacheScenario.java b/src/com/mostc/pftt/scenario/OpcacheScenario.java index 7a412ad..a284134 100644 --- a/src/com/mostc/pftt/scenario/OpcacheScenario.java +++ b/src/com/mostc/pftt/scenario/OpcacheScenario.java @@ -97,22 +97,22 @@ public class OpcacheScenario extends CodeCacheScenario { @Overridable protected DllVersion getDllPath53TS(Host host) { - return new DllVersion(host.getPfttDir()+"/cache/dep/opcache/php_opcache-7.0.2-5.3-ts-vc9-x86/php_opcache.dll", "7.0.2"); + return new DllVersion(host.getPfttCacheDir()+"/dep/opcache/php_opcache-7.0.2-5.3-ts-vc9-x86/php_opcache.dll", "7.0.2"); } @Overridable protected DllVersion getDllPath53NTS(Host host) { - return new DllVersion(host.getPfttDir()+"/cache/dep/opcache/php_opcache-7.0.2-5.3-nts-vc9-x86/php_opcache.dll", "7.0.2"); + return new DllVersion(host.getPfttCacheDir()+"/dep/opcache/php_opcache-7.0.2-5.3-nts-vc9-x86/php_opcache.dll", "7.0.2"); } @Overridable protected DllVersion getDllPath54TS(Host host) { - return new DllVersion(host.getPfttDir()+"/cache/dep/opcache/php_opcache-7.0.2-5.4-ts-vc9-x86/php_opcache.dll", "7.0.2"); + return new DllVersion(host.getPfttCacheDir()+"/dep/opcache/php_opcache-7.0.2-5.4-ts-vc9-x86/php_opcache.dll", "7.0.2"); } @Overridable protected DllVersion getDllPath54NTS(Host host) { - return new DllVersion(host.getPfttDir()+"/cache/dep/opcache/php_opcache-7.0.2-5.4-nts-vc9-x86/php_opcache.dll", "7.0.2"); + return new DllVersion(host.getPfttCacheDir()+"/dep/opcache/php_opcache-7.0.2-5.4-nts-vc9-x86/php_opcache.dll", "7.0.2"); } public DllVersion getDllPath(ConsoleManager cm, Host host, PhpBuild build) { diff --git a/src/com/mostc/pftt/scenario/SMBCAScenario.java b/src/com/mostc/pftt/scenario/SMBCAScenario.java index 04fcf8a..4cf63e0 100644 --- a/src/com/mostc/pftt/scenario/SMBCAScenario.java +++ b/src/com/mostc/pftt/scenario/SMBCAScenario.java @@ -44,7 +44,7 @@ public class SMBCAScenario extends SMBScenario { protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { TempFileExecOutput teo = remote_host.powershell(getClass(), cm, "New-SmbShare -Name "+dir.share_name+" -Path "+dir.remote_path+" -Scope "+remote_host.getHostname()+" -FullControl "+remote_host.getHostname()+"\\"+remote_host.getUsername(), AHost.ONE_MINUTE); teo.printCommandAndOutput(EPrintType.CLUE, getClass(), cm); - return teo.cleanupIfSuccess(remote_host); + return teo.cleanupIsSuccess(remote_host); } @Override diff --git a/src/com/mostc/pftt/scenario/SMBDFSScenario.java b/src/com/mostc/pftt/scenario/SMBDFSScenario.java index f122148..3fc2b0e 100644 --- a/src/com/mostc/pftt/scenario/SMBDFSScenario.java +++ b/src/com/mostc/pftt/scenario/SMBDFSScenario.java @@ -242,7 +242,7 @@ public class SMBDFSScenario extends SMBScenario { try { TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, AHost.FOUR_HOURS); teo.printCommandAndOutput(EPrintType.CLUE, getClass(), cm); - if (teo.cleanupIfSuccess(remote_host)) { + if (teo.cleanupIsSuccess(remote_host)) { cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "DFS Feature Installed"); diff --git a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java index 74e17e5..d348abb 100644 --- a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java +++ b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java @@ -108,7 +108,7 @@ public class SMBDeduplicationScenario extends SMBScenario { final TempFileExecOutput eo = remote_host.powershell(getClass(), cm, "Start-Dedupjob -Volume "+volume+" -Type Optimization -Wait", AHost.FOUR_HOURS); eo.printCommandAndOutput(EPrintType.CLUE, getClass(), cm); - if (eo.cleanupIfSuccess(remote_host)) { + if (eo.cleanupIsSuccess(remote_host)) { // // log REPARSEPOINT QUERY to show if reparse point/deduplication was really setup @@ -164,7 +164,7 @@ public class SMBDeduplicationScenario extends SMBScenario { cm.println(EPrintType.IN_PROGRESS, getClass(), "Starting to Install Deduplication on: "+remote_host); TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, AHost.ONE_MINUTE * 10); teo.printCommandAndOutput(EPrintType.CLUE, getClass(), cm); - if (teo.cleanupIfSuccess(remote_host)) { + if (teo.cleanupIsSuccess(remote_host)) { // don't delete tmp_file if it failed to help user see why cm.println(EPrintType.IN_PROGRESS, getClass(), "Deduplication Feature Installed."); diff --git a/src/com/mostc/pftt/scenario/Scenario.java b/src/com/mostc/pftt/scenario/Scenario.java index b0d2658..62997a0 100644 --- a/src/com/mostc/pftt/scenario/Scenario.java +++ b/src/com/mostc/pftt/scenario/Scenario.java @@ -46,7 +46,6 @@ public abstract class Scenario { return false; } - // TODO @Overridable public Class<?> getSerialKey(EScenarioSetPermutationLayer layer) { return getClass(); @@ -204,6 +203,14 @@ public abstract class Scenario { scenario_set.add(new EnchantScenario()); } + public int getApprovedInitialThreadPoolSize(AHost host, int threads) { + return threads; + } + + public int getApprovedMaximumThreadPoolSize(AHost host, int threads) { + return threads; + } + /** writes Scenario to XML * * @param serial diff --git a/src/com/mostc/pftt/scenario/ScenarioSet.java b/src/com/mostc/pftt/scenario/ScenarioSet.java index f6da09c..80dba2f 100644 --- a/src/com/mostc/pftt/scenario/ScenarioSet.java +++ b/src/com/mostc/pftt/scenario/ScenarioSet.java @@ -231,12 +231,28 @@ public class ScenarioSet extends ArrayList<Scenario> { * @return */ public static List<ScenarioSet> permuteScenarioSets(EScenarioSetPermutationLayer layer, List<Scenario> scenarios) { - HashMap<Class<?>,List<Scenario>> map = new HashMap<Class<?>,List<Scenario>>(); + HashMap<Object,List<ScenarioSet>> version_map = new HashMap<Object,List<ScenarioSet>>(); + for ( Scenario s : scenarios ) { + if (!(s instanceof DatabaseScenario)) + continue; + // TODO temp + Object v = ((DatabaseScenario)s).version; + version_map.put(v, p(layer, scenarios)); + } + if (version_map.isEmpty()) + return p(layer, scenarios); + List<ScenarioSet> out = new ArrayList<ScenarioSet>(); + for ( List<ScenarioSet> a : version_map.values() ) + out.addAll(a); + return out; + } + static List<ScenarioSet> p(EScenarioSetPermutationLayer layer, List<Scenario> scenarios) { + HashMap<Object,List<Scenario>> map = new HashMap<Object,List<Scenario>>(); for ( Scenario scenario : scenarios ) { if (layer!=null && layer.reject(scenario)) continue; - Class<?> clazz = scenario.getSerialKey(layer); + Object clazz = scenario.getSerialKey(layer); // List<Scenario> list = map.get(clazz); if (list==null) { @@ -319,10 +335,12 @@ public class ScenarioSet extends ArrayList<Scenario> { name = s.processNameAndVersionInfo(name); return name; } - + public static ScenarioSet parse(String name) { + // TODO result_pack_mgr as param, throw NPE if not given (this method is only to be used there) ScenarioSet s = new ScenarioSet(); s.str = name; + s.sorted = true; return s; } diff --git a/src/com/mostc/pftt/scenario/ScenarioSetSetup.java b/src/com/mostc/pftt/scenario/ScenarioSetSetup.java index 3331ea9..c55f820 100644 --- a/src/com/mostc/pftt/scenario/ScenarioSetSetup.java +++ b/src/com/mostc/pftt/scenario/ScenarioSetSetup.java @@ -1,5 +1,6 @@ package com.mostc.pftt.scenario; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -88,6 +89,14 @@ public class ScenarioSetSetup implements IClosable { this.setups = setups; this.name_version = name_version; } + + public Collection<Scenario> getScenarios() { + return setups.keySet(); + } + + public Collection<IScenarioSetup> getSetups() { + return setups.values(); + } public String getNameWithVersionInfo() { return name_version; diff --git a/src/com/mostc/pftt/scenario/WinCacheUScenario.java b/src/com/mostc/pftt/scenario/WinCacheUScenario.java index d84ef48..2b37fe4 100644 --- a/src/com/mostc/pftt/scenario/WinCacheUScenario.java +++ b/src/com/mostc/pftt/scenario/WinCacheUScenario.java @@ -1,6 +1,7 @@ package com.mostc.pftt.scenario; import com.github.mattficken.Overridable; +import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.Host; import com.mostc.pftt.model.core.EBuildBranch; import com.mostc.pftt.model.core.PhpBuild; @@ -18,18 +19,28 @@ import com.mostc.pftt.results.ConsoleManager; // TODO mediawiki support // TODO windebug integration - wincache includes the .PDB symbol file public abstract class WinCacheUScenario extends UserCacheScenario { + + @Override + public int getApprovedInitialThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 2; + } + + @Override + public int getApprovedMaximumThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 3; + } @Overridable protected String getDllPath55Plus(Host host) { - return host.getPfttDir()+"/cache/dep/wincache/wincache-1.3.4.1-dev-5.5-nts-vc11-x86/php_wincache.dll"; + return host.getPfttCacheDir()+"/dep/wincache/wincache-1.3.5-5.5-nts-vc11-x86/php_wincache.dll"; } @Overridable protected String getDllPath54(Host host) { - return host.getPfttDir()+"/cache/dep/wincache/wincache-1.3.4-5.4-nts-vc9-x86/php_wincache.dll"; + return host.getPfttCacheDir()+"/dep/wincache/wincache-1.3.4-5.4-nts-vc9-x86/php_wincache.dll"; } @Overridable protected String getDllPath53(Host host) { - return host.getPfttDir()+"/cache/dep/wincache/wincache-1.3.4-5.3-nts-vc9-x86/php_wincache.dll"; + return host.getPfttCacheDir()+"/dep/wincache/wincache-1.3.4-5.3-nts-vc9-x86/php_wincache.dll"; } // @see http://us.php.net/manual/en/wincache.configuration.php @@ -87,10 +98,18 @@ public abstract class WinCacheUScenario extends UserCacheScenario { @Override public boolean isSupported(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - // don't run WinCache on Apache-ModPHP (Apache CGI probably ok) - // - // not sure if its supported on scenarios other than CLI or IIS (or builtin-web?) - return host.isWindows() && build.isNTS(host) && !scenario_set.contains(ApacheModPHPScenario.class); + return host.isWindows() + && build.isX86() + && build.isNTS(host) + && ( + // LATER? Apache FastCGI support on Windows + scenario_set.contains(CliScenario.class) + || scenario_set.contains(IISScenario.class) + // WinCacheU should support builtin web server b/c (low priority though): + // web developers use wincache's user cache in their applications + // web developers like to use the builtin web server to run/test their application + || scenario_set.contains(BuiltinWebServerScenario.class) + ); } @Override diff --git a/src/com/mostc/pftt/scenario/XDebugProfilingScenario.java b/src/com/mostc/pftt/scenario/XDebugProfilingScenario.java index 2854283..51d46f0 100644 --- a/src/com/mostc/pftt/scenario/XDebugProfilingScenario.java +++ b/src/com/mostc/pftt/scenario/XDebugProfilingScenario.java @@ -1,8 +1,11 @@ package com.mostc.pftt.scenario; +import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.Host; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; +import com.mostc.pftt.results.AbstractPhpUnitRW; +import com.mostc.pftt.results.AbstractPhptRW; import com.mostc.pftt.results.ConsoleManager; /** @@ -12,26 +15,76 @@ import com.mostc.pftt.results.ConsoleManager; */ public class XDebugProfilingScenario extends XDebugScenario { + public static final String OUTPUT_DIR = "xdebug.profiler_output_dir"; @Override public String getName() { return "XDebug-Profiling"; } + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { + return new ProfilingScenarioSetup(); + } + @Override public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, PhpIni ini) { if (super.setup(cm, host, build, ini)==SETUP_FAILED) return SETUP_FAILED; + setup(ini); + // #setPHPTWriter and #setPhpUnitWriter get called first to store it in result-pack + // @see AbstractLocalTestPackRunner$TestPackThread#exec_jobs + // store in $TEMP unless/until they are called though (as a backup, this shouldn't happen though) + ini.putSingle(OUTPUT_DIR, host.getTempDir()); + + return new ProfilingScenarioSetup(); + } + + protected void setup(PhpIni ini) { ini.putSingle("xdebug.profiler_append", "0"); ini.putSingle("xdebug.profiler_enable", "1"); - // TODO include test name // include script name in file name ini.putSingle("xdebug.profiler_output_name", "pftt.%p.%s.cachegrind"); - // TODO store in test-pack - ini.putSingle("xdebug.profiler_output_dir", host.getTempDir()); + } + + protected class ProfilingScenarioSetup extends SimpleScenarioSetup { + + @Override + public boolean isNeededPhpUnitWriter() { + return true; + } + + @Override + public void setPhpUnitWriter(AHost runner_host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhpIni ini, AbstractPhpUnitRW phpunit) { + setup(ini); + ini.putSingle(OUTPUT_DIR, phpunit.getPath()); + } + + @Override + public void setPHPTWriter(AHost runner_host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhpIni ini, AbstractPhptRW phpt) { + setup(ini); + ini.putSingle(OUTPUT_DIR, phpt.getPath()); + } + + @Override + public boolean isNeededPhptWriter() { + return true; + } + + @Override + public String getNameWithVersionInfo() { + return getName(); // TODO auto detect + } + + @Override + public String getName() { + return XDebugProfilingScenario.this.getName(); + } + + @Override + public void close(ConsoleManager cm) { + } - return SETUP_SUCCESS; } } diff --git a/src/com/mostc/pftt/scenario/app/JoomlaScenario.groovy b/src/com/mostc/pftt/scenario/app/JoomlaScenario.groovy index eec9073..c6d61ba 100644 --- a/src/com/mostc/pftt/scenario/app/JoomlaScenario.groovy +++ b/src/com/mostc/pftt/scenario/app/JoomlaScenario.groovy @@ -30,7 +30,7 @@ public class JoomlaScenario extends ZipDbApplication { @Override public boolean isImplemented() { - return false; + return true; } @Override @@ -42,7 +42,7 @@ public class JoomlaScenario extends ZipDbApplication { protected boolean configure(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, String app_dir) { // TODO Auto-generated method stub - host.open("joomla/joomla.xml"); + /*host.open("joomla/joomla.xml"); def xml = """ <?xml version="1.0" encoding="UTF-8" ?> - <extension version="3.0" type="file" method="upgrade"> @@ -95,9 +95,9 @@ public class JoomlaScenario extends ZipDbApplication { <server type="collection">http://update.joomla.org/jed/list.xml</server> </updateservers> </extension> - """ + """*/ - return false; + return true; } } diff --git a/src/com/mostc/pftt/util/HostEnvUtil.java b/src/com/mostc/pftt/util/HostEnvUtil.java index 4ff766c..a59f41d 100644 --- a/src/com/mostc/pftt/util/HostEnvUtil.java +++ b/src/com/mostc/pftt/util/HostEnvUtil.java @@ -74,8 +74,8 @@ public final class HostEnvUtil { regDel(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Debugger"); // IMPORTANT: don't delete this key, change the value otherwise (if windbg installed) werfault.exe will - // still launch windbg... won't if set to 0x2. - regQueryAdd(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Auto", "0x2", REG_DWORD); + // still launch windbg... won't if set to 0x1 + regQueryAdd(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Auto", "0x1", REG_DWORD); } if ( a || b || c ) { diff --git a/src/com/mostc/pftt/util/WinDebugManager.java b/src/com/mostc/pftt/util/WinDebugManager.java index c195311..94dc9e7 100644 --- a/src/com/mostc/pftt/util/WinDebugManager.java +++ b/src/com/mostc/pftt/util/WinDebugManager.java @@ -123,7 +123,7 @@ public class WinDebugManager extends DebuggerManager { // -n => noisy symbol load => provide extra info about symbol loading to trace any symbol problems sb.append(" -n"); // -WF => provide default workspace file, which will automatically dock the command window within the windebug window - String workspace_file = host.fixPath(host.joinIntoOnePath(host.getPfttDir(), "\\bin\\pftt_workspace.WEW")); + String workspace_file = host.fixPath(host.joinIntoOnePath(host.getPfttBinDir(), "\\pftt_workspace.WEW")); if (host.exists(workspace_file)) { sb.append(" -WF \"");sb.append(workspace_file);sb.append("\""); }