Commits

Alex Turcu committed 905edfa

JVM Continuations (requires non-standard jvm + patch). Enhanced counter app.

Comments (0)

Files changed (10)

     def __init__(self, h5name = "tests.h5", reset=False):
         if os.path.exists(h5name) and not reset:
             self.h5 = openFile(h5name, mode="a")
-            self.group = self.h5.root.main3
+            self.group = self.h5.root.main4
             self.table = self.group.tests
         else:
             self.h5 = openFile(h5name, mode="w", title="Hyflow2 tests file")
     xa = data.keys()
     xa = sorted(xa, key = lambda x: int(x))
     ya = [data[x] for x in xa]
-    pylab.loglog(xa, ya, line, label=label)
+    pylab.plot(xa, ya, line, label=label)
 
 def plot_series(filt, line="k-", label=""):
+    print filt
     data = {}
     mean = {}
     std = {}
     for it in hy.table.where(filt):
+        print ".",
         n = it["hyflow_nodes"]
         if n not in data.keys():
             data[n] = []
     
     #plot_series('(tag == "hynetty local")', "k-", "local 1ms")
     #plot_series('(tag == "hynetty distrib")', "r-", "3pc 1ms")
+    bench = "linkedlist"
+    ax = pylab.subplot(111)
     
-    ax = pylab.subplot(111)
-    plot_series('(bench == "bank")', "kx-", "bank")
-    plot_series('(bench == "bst")', "bx-", "bst")
+    #for test in ['"sweep-flat"', '"sweep-actuallyflat"','"sweep-flat-nocondsync"']:
+    #for test in ['"sweep-actuallyflat-3ops"', '"sweep-closed-3ops"']:
+    for test in ['"sweep-closed-3ops-contended"']:
+        if test not in ["hytest"]:
+            plot_series('(bench == "%s") & (hyflow_logging_testId == "%s")' % (bench, test.replace('"', '\\"')), "x-", test)
+    
+    #for test in ['"sweep-check-flatemul-30"', '"sweep-check-5"', '"sweep-check-30"', '"sweep-check-100"' ]:
+    #for test in ['"sweep-check-3op-5"']:
+    for test in ['"sweep-check-5-3op-contended"']:
+        if test not in ["hytest"]:
+            plot_series('(bench == "cp-%s") & (hyflow_logging_testId == "%s")' % (bench, test.replace('"', '\\"')), "x-", test)
     
     pylab.legend(loc="best")
     pylab.grid(True, which="both")
-    pylab.minorticks_on()
-    ax.set_xticklabels(range(2, 10) + [20], minor=True)
-    ax.set_xlim(2, 20)
-    ax.set_ylim(1000, 40000)
+    #pylab.minorticks_on()
+    #ax.set_xticklabels(range(2, 10) + [20], minor=True)
+    #ax.set_xlim(2, 20)
+    #ax.set_ylim(1000, 40000)
     pylab.show()
 
 if __name__ == "__main__":
     hy = HyTests(reset=False)
-    gather_results("result-lost.txt", hy.row)
+    #gather_results("result-lost.txt", hy.row)
     #gather_results("result-rosella.txt", hy.row)
     #hy.h5.flush()
     
+    testNames = set(hy.table.cols.hyflow_logging_testId[:])
+    benchmarks = set(hy.table.cols.bench[:])
+    print testNames
+    print benchmarks
     main()
-    #print set(hy.table.cols.tag[:])
     hy.h5.close()
 
 	}
 	
 	motstm {
-		conditionalSync = true
+		conditionalSync = false
 		closedNesting = false
 		alwaysPessimistic = false
 		allowPessimistic = false
 
 	haistm {
 		checkpointProb = 30
-		emulateFlat = true
+		emulateFlat = false
 	}
 	
 	logging {
 			keyRange = 100
 		}
                 bank {   }
-                counter {   }
+                counter { 
+			steps = "step1,step2,step3"
+			#steps = "default"
+			_default {
+				pool = 1
+				ops = 1
+			}
+			_step1 {
+				pool = 500
+				ops = 25
+			}
+			_step2 {
+				pool = 8
+				ops = 2
+			}
+			_step3 {
+				pool = 500
+				ops = 5
+			}
+		}
 		skiplist {
 			maxLevel = 6
 			probability = 0.5

hyflow-benchmarks/src/main/scala/org/hyflow/benchmarks/counter/CounterBenchmark.scala

 
 import org.hyflow.api._
 import org.hyflow.benchmarks._
-import org.hyflow.core.directory.Tracker
+import org.hyflow.core.util._
+import org.hyflow.Hyflow
 import org.eintr.loglady.Logging
 import scala.concurrent.stm._
 
-
 class CounterBenchmark extends Benchmark with Logging {
 	val name = "counter"
-	
+
+	val COUNTER_STEPS = HyflowConfig.cfg[String](
+		"hyflow.workload.counter.steps").split(",").toList.map { x =>
+			val pool = HyflowConfig.cfg[String]("hyflow.workload.counter._%s.pool" format x)
+			val ops = HyflowConfig.cfg[String]("hyflow.workload.counter._%s.ops" format x)
+			Map("name" -> x, "pool" -> pool, "ops" -> ops)
+		}
+
 	def benchInit() {
 		val slice = getLocalSlice
 		if (slice.contains(0)) {
-			new Counter("ctr")
+			for (step <- COUNTER_STEPS) {
+				for (i <- 0 to Integer.parseInt(step("pool")))
+					new Counter("ctr_%s_%d".format(step("name"), i))
+			}
 		}
 	}
-	
+
 	def benchIter() {
-		if (randomlyReadOnly) 
-			CounterOps.get
-		else 
-			CounterOps.inc()
+		def randId(x: Map[String,String]): String = {
+			"ctr_%s_%d".format(x("name"), rand.nextInt(Integer.parseInt(x("pool"))))
+		}
+		val ids = COUNTER_STEPS.map { x => randomObjIdSet(Integer.parseInt(x("ops")), () => randId(x)) }
+		if (randomlyReadOnly)
+			CounterOps.get(ids)
+		else
+			CounterOps.inc(ids)
 	}
-	
+
 	def benchCheck() = true
 }
 
 object CounterOps {
-	def inc() {
+
+	def inc(ids: List[Array[String]]) {
 		atomic { implicit txn =>
-			val ctr = Tracker.open[Counter]("ctr")
-			ctr.v() = ctr.v() + 1
+			var skipfirst = true
+			for (step <- ids) {
+				if (skipfirst) {
+					skipfirst = false
+				}
+				// else checkpoint!
+				for (ctrid <- step) {
+					val ctr = Hyflow.dir.open[Counter](ctrid)
+					ctr.v() = ctr.v() + 1
+				}
+			}
 		}
 	}
-	
-	def get {
+
+	def get(ids: List[Array[String]]) {
 		atomic { implicit txn =>
-			val ctr = Tracker.open[Counter]("ctr")
-			ctr.v()
+			var skipfirst = true
+			for (step <- ids) {
+				if (skipfirst) {
+					skipfirst = false
+				}
+				// else checkpoint!
+				for (ctrid <- step) {
+					val ctr = Hyflow.dir.open[Counter](ctrid)
+					ctr.v()
+				}
+			}
 		}
 	}
 }

hyflow-checkpoints/src/main/scala/org/hyflow/benchmarks/BenchApp.scala

 }
 
 object BenchApp extends App with Logging {
-	import org.hyflow.benchmarks.HyflowClassLoader
-	import java.net.URL
 
 	val arguments = args
 	val argsStr = WrappedArray.make[String](args).toList.toString
 	var benchName: String = _
 
-	val cl = new HyflowClassLoader(
-		Array[URL](new URL("file://hyflow-checkpoints_2.9.1-0.0.1.jar")),
-		this.getClass.getClassLoader()
-	)
-
-	cl.setParentFirst(false)
-
-	cl.addSystemPackageRoot("java")
-	cl.addSystemPackageRoot("javax")
-	cl.addSystemPackageRoot("scala")
-	cl.addSystemPackageRoot("sun")
-	
-	
-	cl.addSystemPackageRoot("akka")
-	cl.addSystemPackageRoot("org")
-	cl.addSystemPackageRoot("de")
-	cl.addSystemPackageRoot("com")
-	cl.addSystemPackageRoot("ch")
-	
-	cl.addIgnored("org.hyflow.core.util")
-	//cl.addIgnored("org.hyflow.api.HObj")
-	cl.addIgnored("org.hyflow.benchmarks.BenchApp$")
-	
-	
-	cl.addLoaderPackageRoot("org.hyflow")
-
-	cl.addTransformedPackageRoot("org.hyflow.benchmarks")
-	cl.addTransformedPackageRoot("org.hyflow.benchmarks")
-	cl.addTransformedPackageRoot("org.hyflow.core.directory.CpTracker")
-	cl.addTransformedPackageRoot("scala.concurrent.stm.haistm")
-	
-	cl.addLoaderPackageRoot("scala.concurrent.stm.haistm")
-	cl.addLoaderPackageRoot("scala.concurrent.stm.motstm")
-	
 	System.setProperty("logback.configurationFile", new java.io.File("etc/logback.xml").getAbsolutePath)
 	for (arg <- args) {
 			val res = arg.split("=", 2)
 			}
 		}
 	
-	cl.forceLoadClass("org.hyflow.benchmarks.counter.Counter")
-	cl.forceLoadClass("org.hyflow.benchmarks.AggrStats")
 	
-	val thrd: Thread = cl.loadClass("org.hyflow.benchmarks.BenchThread").newInstance().asInstanceOf[Thread]
-	thrd.setContextClassLoader(cl)
+	val thrd: Thread = new BenchThread()
 	thrd.start()
 }

hyflow-checkpoints/src/main/scala/org/hyflow/benchmarks/HyflowClassLoader.scala

-package org.hyflow.benchmarks
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-import scala.collection.mutable
-
-import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
-import org.apache.commons.javaflow.bytecode.transformation.asm.AsmClassTransformer;
-
-import java.io.{ByteArrayOutputStream, IOException, InputStream}
-import java.net.{URL, URLClassLoader}
-import java.security._
-
-import org.eintr.loglady.Logging
-
-private object HyflowClassLoader {
-
-	def appendDot(str: String): String = {
-		if (str.endsWith("."))
-			str + '.';
-		else
-			str;
-	}
-
-	def fixNullParent(classLoader: ClassLoader): ClassLoader = {
-		if (classLoader != null) {
-			return classLoader;
-		} else {
-			return null //getSystemClassLoader();
-		}
-	}
-}
-
-/**
- * {@link URLClassLoader} with bytecode instrumentation for javaflow.
- *
- * <p>
- * This class loader is useful where the application can set up multiple
- * class loaders (such as in a container environment,
- * <a href="http://classworlds.codehaus.org/">ClassWorlds</a>, or
- * <a href="http://forehead.werken.com/">Forehead</a>) and when you can
- * isolate the continuation-enabled portion of your application into a separate
- * jar file.
- */
-import HyflowClassLoader._
-class HyflowClassLoader(urls: Array[URL], parent: ClassLoader, transformer: ResourceTransformer)
-	extends URLClassLoader(urls, fixNullParent(parent)) with Logging {
-
-	private var myTransformer: ResourceTransformer = _
-
-	/**
-	 * Indicates whether the parent class loader should be
-	 * consulted before trying to load with this class loader.
-	 */
-	private var parentFirst = false
-
-	/**
-	 * These are the package roots that are to be loaded by the parent class
-	 * loader regardless of whether the parent class loader is being searched
-	 * first or not.
-	 */
-	val systemPackages = mutable.Set[String]()
-
-	/**
-	 * These are the package roots that are to be loaded by this class loader
-	 * regardless of whether the parent class loader is being searched first
-	 * or not.
-	 */
-	val loaderPackages = mutable.Set[String]()
-	/**
-	 * Only these packages will be bytecode transformed.
-	 */
-	val transformPackages = mutable.Set[String]()
-	
-	val ignorePackages = mutable.Set[String]()
-
-	/**
-	 * Whether or not this classloader will ignore the base
-	 * classloader if it can't find a class.
-	 *
-	 * @see #setIsolated(boolean)
-	 */
-	var ignoreBase = false;
-
-	/* The context to be used when loading classes and resources */
-	private var acc: AccessControlContext = _;
-
-	private var BUFFER_SIZE = 4096;
-
-	/**
-	 * Creates a classloader by using the classpath given.
-	 *
-	 * @param urls
-	 *      The URLs from which to load classes and resources
-	 * @param parent
-	 *      The parent classloader to which unsatisfied loading
-	 *      attempts are delegated. May be <code>null</code>,
-	 *      in which case the {@link ClassLoader#getSystemClassLoader() system classloader}
-	 *      is used as the parent.
-	 * @param transformer
-	 *      This transformer is used to perform the byte-code enhancement.
-	 *      May not be null.
-	 */
-	// constructor
-	if (transformer == null)
-		throw new IllegalArgumentException();
-	this.myTransformer = transformer;
-	acc = AccessController.getContext();
-
-	def this(urls: Array[URL], parent: ClassLoader) {
-		this(urls, parent, new AsmClassTransformer());
-	}
-	// end constructor
-
-	/**
-	 * Control whether class lookup is delegated to the parent loader first
-	 * or after this loader. Use with extreme caution. Setting this to
-	 * false violates the class loader hierarchy and can lead to Linkage errors
-	 *
-	 * @param parentFirst if true, delegate initial class search to the parent
-	 *                    classloader.
-	 */
-	def setParentFirst(parentFirst: Boolean) {
-		this.parentFirst = parentFirst;
-	}
-
-	/**
-	 * Sets whether this classloader should run in isolated mode. In
-	 * isolated mode, classes not found on the given classpath will
-	 * not be referred to the parent class loader but will cause a
-	 * ClassNotFoundException.
-	 *
-	 * @param isolated Whether or not this classloader should run in
-	 *                 isolated mode.
-	 */
-	def setIsolated(isolated: Boolean) {
-		ignoreBase = isolated;
-	}
-
-	/**
-	 * Adds a package root to the list of packages which must be loaded on the
-	 * parent loader.
-	 *
-	 * All subpackages are also included.
-	 *
-	 * @param packageRoot The root of all packages to be included.
-	 *                    Should not be <code>null</code>.
-	 */
-	def addSystemPackageRoot(packageRoot: String) {
-		synchronized {
-			systemPackages.add(appendDot(packageRoot));
-		}
-	}
-
-	/**
-	 * Adds a package root to the list of packages which must be loaded using
-	 * this loader.
-	 *
-	 * All subpackages are also included.
-	 *
-	 * @param packageRoot The root of all packages to be included.
-	 *                    Should not be <code>null</code>.
-	 */
-	def addLoaderPackageRoot(packageRoot: String) {
-		synchronized {
-			loaderPackages.add(appendDot(packageRoot));
-		}
-	}
-	
-	/**
-	 * Adds a package to be transformed.
-	 */
-	def addTransformedPackageRoot(packageRoot: String) {
-		synchronized {
-			transformPackages.add(appendDot(packageRoot));
-		}
-	}
-	
-	/**
-	 * Adds a package to the ignored list.
-	 */
-	def addIgnored(packageRoot: String) {
-		synchronized {
-			ignorePackages.add(appendDot(packageRoot));
-		}
-	}
-
-	/**
-	 * Loads a class through this class loader even if that class is available
-	 * on the parent classpath.
-	 *
-	 * This ensures that any classes which are loaded by the returned class
-	 * will use this classloader.
-	 *
-	 * @param classname The name of the class to be loaded.
-	 *                  Must not be <code>null</code>.
-	 *
-	 * @return the required Class object
-	 *
-	 * @exception ClassNotFoundException if the requested class does not exist
-	 *                                   on this loader's classpath.
-	 */
-	def forceLoadClass(classname: String): Class[_] = {
-		log.debug("force loading " + classname);
-
-		val theClass = findLoadedClass(classname);
-		if (theClass == null) {
-			findClass(classname);
-		} else
-			theClass;
-	}
-
-	/**
-	 * Tests whether or not the parent classloader should be checked for
-	 * a resource before this one. If the resource matches both the
-	 * "use parent classloader first" and the "use this classloader first"
-	 * lists, the latter takes priority.
-	 *
-	 * @param resourceName The name of the resource to check.
-	 *                     Must not be <code>null</code>.
-	 *
-	 * @return whether or not the parent classloader should be checked for a
-	 *         resource before this one is.
-	 */
-	def isParentFirst(resourceName: String): Boolean = {
-		// default to the global setting and then see
-		// if this class belongs to a package which has been
-		// designated to use a specific loader first
-		// (this one or the parent one)
-
-		// XXX - shouldn't this always return false in isolated mode?
-		synchronized {
-			var useParentFirst = parentFirst;
-
-			for (packageName <- systemPackages) {
-				if (resourceName.startsWith(packageName)) {
-					useParentFirst = true;
-				}
-			}
-
-			for (packageName <- loaderPackages) {
-				if (resourceName.startsWith(packageName)) {
-					useParentFirst = false;
-				}
-			}
-			
-			if (ignorePackages.find(resourceName.startsWith(_)) != None)
-				useParentFirst = true
-
-			return useParentFirst;
-		}
-	}
-
-	/**
-	 * Loads a class with this class loader.
-	 *
-	 * This class attempts to load the class in an order determined by whether
-	 * or not the class matches the system/loader package lists, with the
-	 * loader package list taking priority. If the classloader is in isolated
-	 * mode, failure to load the class in this loader will result in a
-	 * ClassNotFoundException.
-	 *
-	 * @param classname The name of the class to be loaded.
-	 *                  Must not be <code>null</code>.
-	 * @param resolve <code>true</code> if all classes upon which this class
-	 *                depends are to be loaded.
-	 *
-	 * @return the required Class object
-	 *
-	 * @exception ClassNotFoundException if the requested class does not exist
-	 * on the system classpath (when not in isolated mode) or this loader's
-	 * classpath.
-	 */
-	override protected def loadClass(classname: String, resolve: Boolean): Class[_] = {
-		// 'sync' is needed - otherwise 2 threads can load the same class
-		// twice, resulting in LinkageError: duplicated class definition.
-		// findLoadedClass avoids that, but without sync it won't work.
-		synchronized {
-			var theClass = findLoadedClass(classname);
-			if (theClass != null) {
-				return theClass;
-			}
-
-			if (isParentFirst(classname)) {
-				try {
-					theClass = getParent().loadClass(classname);
-					log.debug("Class " + classname + " loaded from parent loader "
-						+ "(parentFirst)");
-				} catch {
-					case cnfe: ClassNotFoundException =>
-						theClass = findClass(classname);
-						log.debug("Class " + classname + " loaded from ant loader "
-							+ "(parentFirst)");
-				}
-			} else {
-				try {
-					theClass = findClass(classname);
-					log.debug("Class " + classname + " loaded from ant loader");
-				} catch {
-					case cnfe: ClassNotFoundException =>
-						if (ignoreBase) {
-							throw cnfe;
-						}
-						theClass = getParent().loadClass(classname);
-						log.debug("Class " + classname + " loaded from parent loader");
-				}
-			}
-
-			if (resolve) {
-				resolveClass(theClass);
-			}
-
-			return theClass;
-		}
-	}
-
-	/**
-	 * Define a class given its bytes
-	 *
-	 * @param classData the bytecode data for the class
-	 * @param classname the name of the class
-	 *
-	 * @return the Class instance created from the given data
-	 */
-	protected def defineClassFromData(classData: Array[Byte], classname: String): Class[_] = {
-		return AccessController.doPrivileged(new PrivilegedAction[Class[_]]() {
-			def run(): Class[_] = {
-				// define a package if necessary.
-				val i = classname.lastIndexOf('.');
-				if (i > 0) {
-					val packageName = classname.substring(0, i);
-					val pkg = getPackage(packageName);
-					if (pkg == null) {
-						definePackage(packageName, null, null, null, null, null, null, null);
-					}
-				}
-				
-				def getTransformed(): Array[Byte] = {
-					var j = 0
-					while (true) {
-						try {
-							return myTransformer.transform(classData);
-						} catch {
-							case e: ClassCircularityError =>
-								log.warn("ClassCircularityError: %s", e.getMessage())
-								j += 1
-								if (j > 10) {
-									log.error("Couldn't avoid ClassCircularityError.", e)
-									throw e
-								}
-						}
-					}
-					throw new Exception("HyflowClassLoader bug.")
-				}
-
-				val loadedData = if (transformPackages.find(classname.startsWith(_)) != None) 
-						getTransformed
-					else
-						classData
-				val domain = this.getClass().getProtectionDomain();
-				
-				// DEBUG CODE
-				if (false) {
-					import java.io._
-					val fname = new File("debug/"+classname+".class")
-					fname.createNewFile()
-					
-					val strout = new BufferedOutputStream(new FileOutputStream(fname))
-					strout.write(loadedData)
-					strout.close()
-				}
-				//END DEBUG CODE
-				
-				defineClass(classname, loadedData, 0, loadedData.length, domain);
-			}
-		}, acc);
-	}
-
-	/**
-	 * Reads a class definition from a stream.
-	 *
-	 * @param stream The stream from which the class is to be read.
-	 *               Must not be <code>null</code>.
-	 * @param classname The name of the class in the stream.
-	 *                  Must not be <code>null</code>.
-	 *
-	 * @return the Class object read from the stream.
-	 *
-	 * @exception IOException if there is a problem reading the class from the
-	 * stream.
-	 * @exception SecurityException if there is a security problem while
-	 * reading the class from the stream.
-	 */
-	private def getClassFromStream(stream: InputStream, classname: String): Class[_] = {
-
-		val baos = new ByteArrayOutputStream();
-		try {
-
-			var bytesRead: Int = 0;
-			val buffer = new Array[Byte](BUFFER_SIZE);
-
-			do {				
-				bytesRead = stream.read(buffer, 0, BUFFER_SIZE)
-				if (bytesRead != -1)
-					baos.write(buffer, 0, bytesRead);
-			} while (bytesRead != -1)
-
-			val classData = baos.toByteArray();
-			return defineClassFromData(classData, classname);
-
-		} finally {
-			baos.close();
-		}
-	}
-
-	/**
-	 * Searches for and load a class on the classpath of this class loader.
-	 *
-	 * @param name The name of the class to be loaded. Must not be
-	 *             <code>null</code>.
-	 *
-	 * @return the required Class object
-	 *
-	 * @exception ClassNotFoundException if the requested class does not exist
-	 *                                   on this loader's classpath.
-	 */
-	override def findClass(name: String): Class[_] = {
-		log.debug("Finding class " + name);
-
-		// locate the class file
-		val classFileName = name.replace('.', '/') + ".class";
-
-		val stream = getResourceAsStream(classFileName);
-		if (stream == null)
-			throw new ClassNotFoundException(name);
-
-		try {
-			return getClassFromStream(stream, name);
-		} catch {
-			case e: IOException =>
-				throw new ClassNotFoundException(name, e);
-		} finally {
-			try {
-				stream.close();
-			} catch {
-				case e: IOException =>
-				// ignore
-			}
-		}
-	}
-
-	/**
-	 * Finds the resource with the given name. A resource is
-	 * some data (images, audio, text, etc) that can be accessed by class
-	 * code in a way that is independent of the location of the code.
-	 *
-	 * @param name The name of the resource for which a stream is required.
-	 *             Must not be <code>null</code>.
-	 * @return a URL for reading the resource, or <code>null</code> if the
-	 *         resource could not be found or the caller doesn't have
-	 *         adequate privileges to get the resource.
-	 */
-	override def getResource(name: String): URL = {
-		synchronized {
-			// we need to search the components of the path to see if
-			// we can find the class we want.
-			if (isParentFirst(name)) {
-				return super.getResource(name);
-			}
-
-			// try this class loader first, then parent
-			val url = findResource(name);
-			if (url == null) {
-				getParent().getResource(name);
-			} else
-				url;
-		}
-	}
-}

hyflow-checkpoints/src/main/scala/org/hyflow/benchmarks/counter/CpCounterBenchmark.scala

 import org.hyflow.Hyflow
 import org.hyflow.benchmarks._
 import org.eintr.loglady.Logging
+import org.hyflow.core.util._
 import scala.concurrent.stm._
+import scala.concurrent.stm.haistm._
 
 
 class CpCounterBenchmark extends Benchmark with Logging {
 	val name = "cp-counter"
-	
+
+	val COUNTER_STEPS = HyflowConfig.cfg[String](
+		"hyflow.workload.counter.steps").split(",").toList.map { x =>
+			val pool = HyflowConfig.cfg[String]("hyflow.workload.counter._%s.pool" format x)
+			val ops = HyflowConfig.cfg[String]("hyflow.workload.counter._%s.ops" format x)
+			Map("name" -> x, "pool" -> pool, "ops" -> ops)
+		}
+
 	def benchInit() {
 		val slice = getLocalSlice
 		if (slice.contains(0)) {
-			new Counter("c0")
-			new Counter("c1")
-		}
-	}
-	
-	def benchIter() {
-		val ids = randomObjIdSet(2)
-		if (randomlyReadOnly) {
-			val ctrs = atomic { implicit txn => 
-				val c0 = CpCounterOps.get(ids(0))
-				val c1 = CpCounterOps.get(ids(1))
-				c0 -> c1
-			}
-			log.info("Counter Check: c0 = %s, c1 = %s %s", ctrs._1, ctrs._2, 
-					if (ctrs._1 != ctrs._2) "DIFFER" else "")
-		}
-		else {
-			atomic { implicit txn => 
-				CpCounterOps.inc(ids(0))
-				CpCounterOps.inc(ids(1))
-			}
-			
-			atomic { implicit txn => 
-				CpCounterOps.dec(ids(0))
-				CpCounterOps.dec(ids(1))
+			for (step <- COUNTER_STEPS) {
+				for (i <- 0 to Integer.parseInt(step("pool")))
+					new Counter("ctr_%s_%d".format(step("name"), i))
 			}
 		}
 	}
-	
-	override def randomObjId: String = {
-		"c"+rand.nextInt(2)
+
+	def benchIter() {
+		def randId(x: Map[String,String]): String = {
+			"ctr_%s_%d".format(x("name"), rand.nextInt(Integer.parseInt(x("pool"))))
+		}
+		val ids = COUNTER_STEPS.map { x => randomObjIdSet(Integer.parseInt(x("ops")), () => randId(x)) }
+		if (randomlyReadOnly)
+			CounterOps.get(ids)
+		else
+			CounterOps.inc(ids)
 	}
-	
-	def benchCheck() = {
+
+	def benchCheck() = true
+}
+
+object CounterOps {
+
+	def inc(ids: List[Array[String]]) {
 		atomic { implicit txn =>
-			val c0 = Hyflow.dir.open[Counter]("c0")
-			val c1 = Hyflow.dir.open[Counter]("c1")
-			if (c0.v() == 0 && c1.v() == 0) {
-				log.info("Consistency check PASSED")
-				true
-			} else {
-				log.error("Consistency check FAILED")
-				false 
+			var skipfirst = true
+			for (step <- ids) {
+				if (skipfirst) {
+					skipfirst = false
+				}
+				else HyHai.manualCheckpoint()
+				for (ctrid <- step) {
+					val ctr = Hyflow.dir.open[Counter](ctrid)
+					ctr.v() = ctr.v() + 1
+				}
+			}
+		}
+	}
+
+	def get(ids: List[Array[String]]) {
+		atomic { implicit txn =>
+			var skipfirst = true
+			for (step <- ids) {
+				if (skipfirst) {
+					skipfirst = false
+				} else HyHai.manualCheckpoint()
+				for (ctrid <- step) {
+					val ctr = Hyflow.dir.open[Counter](ctrid)
+					ctr.v()
+				}
 			}
 		}
 	}
 }
 
-private class CpCounterOps {
-	
-	protected lazy val log = org.eintr.loglady.Logger(getClass)
-	
-	//def logg(a: String, b: String) = println(a.format(b))
-	def logg(a: String, b: String, c: String) = log.info(a, b, c)
-	
-	def inc(cname: String) {
-		val res = atomic { implicit txn =>
-			val ctr = Hyflow.dir.open[Counter](cname)
-			ctr.v() = ctr.v() + 1
-			ctr.v()
-		}
-		logg("Counter %s after inc: %s", cname, res toString)
-	}
-	
-	def dec(cname: String) {
-		val res = atomic { implicit txn =>
-			val ctr = Hyflow.dir.open[Counter](cname)
-			ctr.v() = ctr.v() - 1
-			ctr.v()
-		}
-		logg("Counter %s after dec: %s", cname, res toString)
-	}
-	
-	def get(cname: String) = {
-		atomic { implicit txn =>
-			val ctr = Hyflow.dir.open[Counter](cname)
-			ctr.v()
-		}
-	}
-}
-
-private object CpCounterOps extends CpCounterOps
-
-class Counter(val _id: String) extends HObj {
+class Counter(val _id: String) extends HObj with Logging {
 	val v = field(0)
 }

hyflow-checkpoints/src/main/scala/org/hyflow/core/directory/CpTracker.scala

 import org.hyflow.api._
 import org.hyflow.core._
 import scala.concurrent.stm._
-import org.apache.commons.javaflow.Continuation
+//import org.apache.commons.javaflow.Continuation
+import sun.misc.Continuation
 import util.HyflowConfig
 
 class CpTracker extends Tracker {
 		if (scala.util.Random.nextInt(100) < prob) {
 			log.debug("Suspending before opening object.  | id = %s", id)
 			// trigger checkpoint
+			val cont = new Continuation()
 			CheckpointStatus.set(CheckpointInterim())
-			Continuation.suspend()
+			cont.save()
 			
 			log.debug("Returned from suspension for opening object.  | id = %s", id)
 		} else {
 		} catch {
 			case CpRollbackError =>
 				log.debug("Failed to open object. | id = %s", id)
+				val cont = new Continuation()
 				CheckpointStatus.set(CheckpointFailure())
-				Continuation.suspend()
+				cont.save()
+				
 				log.error("This should never be reached")
 				null.asInstanceOf[T]
 		}

hyflow-checkpoints/src/main/scala/scala/concurrent/stm/haistm/HaiInTxn.scala

 import scala.concurrent.stm._
 import scala.concurrent.stm.motstm.MotStats
 import scala.concurrent.stm.motstm.TFAClock
-import org.apache.commons.javaflow.Continuation
+//import org.apache.commons.javaflow.Continuation
+import sun.misc.Continuation
 import org.eintr.loglady.Logging
 import scala.collection.mutable
 import scala.util.Random
 	val _hy_txnid = scala.util.Random.nextInt
 	def getTxnId: Long = (Hyflow._hy_nodeid << 32L) | this._hy_txnid
 
-	class HaiRunCkpt[Z](exec: TxnExecutor, block: InTxn => Z) extends Runnable {
+	class HaiCkptEntry[Z](exec: TxnExecutor, block: InTxn => Z) extends Runnable {
 		def run() {
 			log.debug("Starting to run the atomic block.")
 			try {
 					log.error(e, "Oops, caught something but it's not exception?")
 					CheckpointStatus.set(CheckpointPermFail(null))
 			}
-			Continuation.suspend()
+			// Superfluous save, for consistent handling
+			new Continuation save
+		}
+	}
+	
+	class HaiCkptResume(ckpt: Continuation) extends Runnable {
+		def run() {
+			ckpt.resume(null)
 		}
 	}
 
 
 		if (cont != null) {
 			// if we have a checkpoint, resume there
-			cont = Continuation.continueWith(cont)
+			//cont = Continuation.continueWith(cont)
+			cont = Continuation.enter(new HaiCkptResume(cont), null).asInstanceOf[Continuation]
 		} else {
 			// otherwise, start at beginning
-			cont = Continuation.startWith(new HaiRunCkpt(exec, block))
+			//cont = Continuation.startWith(new HaiRunCkpt(exec, block))
+			cont = Continuation.enter(new HaiCkptEntry(exec, block), null).asInstanceOf[Continuation]
 		}
 
 		(level, cont)
 
 		try {
 			// Start execution
-			var cont = Continuation.startWith(new HaiRunCkpt(exec, block))
+			var cont = Continuation.enter(new HaiCkptEntry(exec, block), null).asInstanceOf[Continuation]
 			log.debug("Returned from first checkpoint.")
 			var prevFailures = 0
 
 						_currentLevel = level
 						// continue
 						log.debug("Continuing...")
-						cont = Continuation.continueWith(cont)
+						//cont = Continuation.continueWith(cont)
+						cont = Continuation.enter(new HaiCkptResume(cont), null).asInstanceOf[Continuation]
 					case res: CheckpointFailure =>
 						log.debug("Checkpoint failure.")
 						prevFailures += 1
 				// Since we abort to the last valid level, it is OK to update txn starting time
 				_currentLevel.root.startTime = rclk
 				CheckpointStatus.set(CheckpointFailure())
-				Continuation.suspend()
+				//Continuation.suspend()
+				new Continuation save
 			}
 		}
 	}

hyflow-checkpoints/src/main/scala/scala/concurrent/stm/haistm/HaiTxnLevel.scala

 import java.util.concurrent.atomic.AtomicReference
 import scala.annotation.tailrec
 import org.eintr.loglady.Logging
-import org.apache.commons.javaflow.Continuation
+//import org.apache.commons.javaflow.Continuation
+import sun.misc.Continuation
 
 private[haistm] class HaiTxnLevel(
 	val txn: HaiInTxn,

hyflow-checkpoints/src/main/scala/scala/concurrent/stm/haistm/HyHai.scala

 
 import org.hyflow.api._
 import scala.concurrent.stm._
+import org.eintr.loglady.Logging
 
 // Interface into MotSTM from Hyflow
-object HyHai extends HyflowBackendAccess {
+object HyHai extends HyflowBackendAccess with Logging {
 	
 	def isPessimisticMode(implicit mt: MaybeTxn): Boolean = {
 		val txn = HaiInTxn.currentOrNull
 		} else
 			None
 	}
+	
+	def manualCheckpoint() {
+		import sun.misc.Continuation
+		import org.hyflow.core._
+		
+		log.debug("Suspending (manual checkpoint).")
+		
+		// trigger checkpoint
+		val cont = new Continuation()
+		CheckpointStatus.set(CheckpointInterim())
+		cont.save()
+		
+		log.debug("Returned from suspension (manual checkpoint).")
+	}
 }