You are viewing a plain text version of this content. The canonical link for it is here.
Posted to olio-commits@incubator.apache.org by ws...@apache.org on 2008/10/20 17:39:20 UTC

svn commit: r706345 [3/5] - in /incubator/olio/workload/rails: ./ trunk/ trunk/bin/ trunk/config/ trunk/config/security/ trunk/deploy/ trunk/lib/ trunk/mysql-connector-java-5.0.6/ trunk/mysql-connector-java-5.0.6/debug/ trunk/mysql-connector-java-5.0.6...

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,1008 @@
+/* The contents of this file are subject to the terms
+ * of the Common Development and Distribution License
+ * (the License). You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://www.sun.com/cddl/cddl.html or
+ * install_dir/legal/LICENSE
+ * See the License for the specific language governing
+ * permission and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL
+ * Header Notice in each file and include the License file
+ * at install_dir/legal/LICENSE.
+ * If applicable, add the following below the CDDL Header,
+ * with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * $Id: UIDriver.java,v 1.26 2008/02/12 03:24:20 akara Exp $
+ *
+ * Copyright 2005 Sun Microsystems Inc. All Rights Reserved
+ */
+package com.sun.web20.driver;
+
+import com.sun.faban.driver.*;
+import com.sun.faban.common.Utilities;
+import com.sun.faban.common.NameValuePair;
+import com.sun.web20.util.RandomUtil;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.util.UserName;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.MultipartPostMethod;
+
+import javax.xml.xpath.XPathExpressionException;
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.logging.Logger;
+
+@BenchmarkDefinition (
+    name    = "Web20Bench",
+    version = "0.3",
+    scaleName = "Concurrent Users"
+
+)
+@BenchmarkDriver (
+    name           = "UIDriver",
+    threadPerScale    = 1
+)
+        // 90/10 Read/Write ratio
+       
+@MatrixMix (
+//    operations = {"HomePage", "Login", , "TagSearch", "EventDetail", "PersonDetail",
+//                  "Logout", "AddEvent",  "AddPerson"},
+    operations = { "HomePage", "Login", "TagSearch", "EventDetail", "PersonDetail", "AddPerson", "AddEvent" },
+
+    mix = { @Row({  0, 10, 50, 35,  0, 5,  0 }), // Home Page
+            @Row({  0,  0, 60, 20,  0, 0, 20 }), // Login
+            @Row({ 20,  5, 40, 30,  0, 5,  0 }), // Tag Search
+            @Row({ 70, 20,  0,  0,  0, 5,  0 }), // Event Detail
+            @Row({  0,  0,  0, 30, 10, 0, 30 }), // Person Detail
+            @Row({ 30, 65,  0,  0, 15, 0,  0 }), // Add Person
+            @Row({  0,  0, 25, 75, 15, 0,  0 })  // Add Event
+          }
+)
+@NegativeExponential (
+    cycleType = CycleType.THINKTIME,
+    cycleMean = 5000,
+    cycleDeviation = 2
+)
+
+public class UIDriver {
+
+    public static final String[] HOME_STATICS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif"
+   };
+
+    public static final String[] EVENTDETAIL_STATICS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif",
+        "/javascripts/tiny_mce/tiny_mce.js",
+        "/javascripts/tiny_mce/themes/simple/editor_template.js",
+        "/javascripts/tiny_mce/langs/en.js",
+        "/javascripts/tiny_mce/themes/simple/css/editor_ui.css",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/javascripts/tiny_mce/themes/simple/images/italic.gif",
+        "/javascripts/tiny_mce/themes/simple/images/underline.gif",
+        "/javascripts/tiny_mce/themes/simple/images/strikethrough.gif",
+        "/javascripts/tiny_mce/themes/simple/images/undo.gif",
+        "/javascripts/tiny_mce/themes/simple/images/separator.gif",
+        "/javascripts/tiny_mce/themes/simple/images/redo.gif",
+        "/javascripts/tiny_mce/themes/simple/images/cleanup.gif",
+        "/javascripts/tiny_mce/themes/simple/images/bullist.gif",
+        "/javascripts/tiny_mce/themes/simple/images/numlist.gif",
+        "/javascripts/tiny_mce/themes/simple/css/editor_content.css"
+    };
+
+    public static final String[] ADDPERSON_STATICS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif",
+        "/javascripts/tiny_mce/tiny_mce.js",
+        "/javascripts/tiny_mce/themes/simple/editor_template.js",
+        "/javascripts/tiny_mce/langs/en.js",
+        "/javascripts/tiny_mce/themes/simple/css/editor_ui.css",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/javascripts/tiny_mce/themes/simple/images/italic.gif",
+        "/javascripts/tiny_mce/themes/simple/images/underline.gif",
+        "/javascripts/tiny_mce/themes/simple/images/strikethrough.gif",
+        "/javascripts/tiny_mce/themes/simple/images/undo.gif",
+        "/javascripts/tiny_mce/themes/simple/images/separator.gif",
+        "/javascripts/tiny_mce/themes/simple/images/redo.gif",
+        "/javascripts/tiny_mce/themes/simple/images/cleanup.gif",
+        "/javascripts/tiny_mce/themes/simple/images/bullist.gif",
+        "/javascripts/tiny_mce/themes/simple/images/numlist.gif",
+        "/javascripts/tiny_mce/themes/simple/css/editor_content.css"
+    };
+
+    public static final String[] ADDEVENT_STATICS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif",
+        "/javascripts/tiny_mce/tiny_mce.js",
+        "/javascripts/tiny_mce/themes/simple/editor_template.js",
+        "/javascripts/tiny_mce/langs/en.js",
+        "/javascripts/tiny_mce/themes/simple/css/editor_ui.css",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/javascripts/tiny_mce/themes/simple/images/italic.gif",
+        "/javascripts/tiny_mce/themes/simple/images/underline.gif",
+        "/javascripts/tiny_mce/themes/simple/images/strikethrough.gif",
+        "/javascripts/tiny_mce/themes/simple/images/undo.gif",
+        "/javascripts/tiny_mce/themes/simple/images/separator.gif",
+        "/javascripts/tiny_mce/themes/simple/images/redo.gif",
+        "/javascripts/tiny_mce/themes/simple/images/cleanup.gif",
+        "/javascripts/tiny_mce/themes/simple/images/bullist.gif",
+        "/javascripts/tiny_mce/themes/simple/images/numlist.gif",
+        "/javascripts/tiny_mce/themes/simple/css/editor_content.css"
+    };
+
+
+    public static final String[] PERSON_STATICS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif"
+    };
+
+    public static final String[] PERSON_GETS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif"
+    };
+
+    public static final String[] TAGSEARCH_STATICS = {
+        "/javascripts/prototype.js",
+        "/javascripts/effects.js",
+        "/javascripts/dragdrop.js",
+        "/javascripts/controls.js",
+        "/javascripts/application.js",
+        "/stylesheets/scaffold.css",
+        "/stylesheets/site.css",
+        "/images/bg_main.png",
+        "/images/bg_header.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/RSS-icon-large.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/main_nav_link_bg.gif",
+        "/images/corner_top_right.png",
+        "/images/corner_top_left.png",
+        "/images/corner_bottom_right.png",
+        "/images/corner_bottom_left.png",
+        "/images/reflec_tile.png",
+        "/images/reflec_right.png",
+        "/images/reflec_left.png",
+        "/images/main_nav_hover_bg.gif"
+    };
+
+    // We just need today's date. java.sql.date does not have any time anyway.
+    public static final java.sql.Date BASE_DATE =
+                                new java.sql.Date(System.currentTimeMillis());
+
+    private DriverContext ctx;
+    private HttpTransport http;
+    private String baseURL;
+    private String personDetailURL;
+    private String tagSearchURL;
+    private String homepageURL, loginURL, logoutURL;
+    private String addEventURL, addPersonURL, eventDetailURL;
+    private String addEventResultURL, addPersonResultURL;
+    private String addAttendeeURL; //GET update.php?id=$eventid
+    private String checkNameURL;
+    // private String updatePageURL; //POST gettextafterinsert.php list=attendees
+    private String fileServiceURL;
+    private String[] homepageStatics, personStatics, personGets,
+    tagSearchStatics, eventDetailStatics, addPersonStatics, addEventStatics;
+    File eventImg, eventThumb, eventPdf, personImg, personThumb;
+    private boolean isLoggedOn = false;
+    private String username;
+    Logger logger;
+    private com.sun.faban.driver.util.Random random;
+    private DateFormat df;
+    private String selectedEvent;
+    private int personsAdded = 0;
+    private int loadedUsers;
+    private boolean isCached;
+    private HashSet<String> cachedURLs = new HashSet<String>();
+    private LinkedHashMap<String, String> loginHeaders =
+            new LinkedHashMap<String, String>();
+    private UIDriverMetrics driverMetrics;
+    private long imgBytes = 0;
+    private int imagesLoaded = 0;
+    private String tagCloudURL;
+
+    public UIDriver() throws XPathExpressionException {
+        ctx = DriverContext.getContext();
+        int scale = ctx.getScale();
+        ScaleFactors.setActiveUsers(scale);
+        http = new HttpTransport();
+        // http.setFollowRedirects(true);
+        logger = ctx.getLogger();
+        random = ctx.getRandom();
+        driverMetrics = new UIDriverMetrics();
+        ctx.attachMetrics(driverMetrics);
+        String hostPorts = ctx.getXPathValue(
+                                "/web20/webServer/fa:hostConfig/fa:hostPorts");
+        List<NameValuePair<Integer>> hostPortList =
+                                            Utilities.parseHostPorts(hostPorts);
+        int loadedScale = Integer.parseInt(
+                                    ctx.getXPathValue("/web20/dbServer/scale"));
+        loadedUsers = 4 * loadedScale;
+        if (scale > loadedScale)
+            throw new FatalException("Data loaded only for " + loadedScale +
+                    " concurrent users. Run is set for " + scale +
+                    " concurrent users. Please load for enough concurrent " +
+                    "users. Run terminating!");
+
+        //String type = ctx.getProperty("serverType");
+        String type = "html";
+        String resourcePath = ctx.getProperty("resourcePath");
+        if (!resourcePath.endsWith(File.separator))
+            resourcePath += File.separator;
+        eventImg = new File(resourcePath + "event.jpg");
+        // logger.info("eventImg: " + eventImg);
+        eventThumb = new File(resourcePath + "event_thumb.jpg");
+        // logger.info("eventThumb: " + eventThumb);
+        eventPdf = new File(resourcePath + "event.pdf");
+        // logger.info("eventPdf: " + eventPdf);
+        personImg = new File(resourcePath + "person.jpg");
+        // logger.info("personImg: " + personImg);
+        personThumb = new File(resourcePath + "person_thumb.jpg");
+        // logger.info("personThumb: " + personThumb);
+
+        int bucket = Utilities.selectBucket(ctx.getThreadId(),
+                            ctx.getClientsInDriver(), hostPortList.size());
+        NameValuePair<Integer> hostPort = hostPortList.get(bucket);
+
+        baseURL = "http://" + hostPort.name + ':' + hostPort.value;
+        personDetailURL = baseURL + "/users/";
+        tagSearchURL = baseURL + "/events/tag_search/";
+        tagCloudURL = baseURL + "/tagCloud." + type;
+        addEventURL = baseURL + "/events/new";
+        addEventResultURL = baseURL + "/events/";
+        addPersonURL = baseURL + "/users/new";
+        addPersonResultURL = baseURL + "/users";
+        homepageURL = baseURL + "/";
+        loginURL = baseURL + "/users/login";
+        logoutURL = baseURL + "/users/logout";
+        addAttendeeURL = baseURL + "/events/";
+        // updatePageURL = baseURL + "/gettextafterinsert." + type;
+        eventDetailURL = baseURL + "/events/";
+        fileServiceURL = baseURL + "/fileService." + type + '?';
+        checkNameURL = baseURL + "/users/check_name";
+
+        homepageStatics = populateList(HOME_STATICS);
+        personStatics = populateList(PERSON_STATICS);
+        personGets = populateList(PERSON_GETS);
+        tagSearchStatics = populateList(TAGSEARCH_STATICS);
+        eventDetailStatics = populateList(EVENTDETAIL_STATICS);
+        addPersonStatics = populateList(ADDPERSON_STATICS);
+        addEventStatics = populateList(ADDEVENT_STATICS);
+
+        loginHeaders.put("Host", hostPort.name + ':' + hostPort.value);
+        loginHeaders.put("User-Agent", "Mozilla/5.0");
+        loginHeaders.put("Accept", "text/xml.application/xml,application/" +
+                "xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;" +
+                "q=0.5");
+        loginHeaders.put("Accept-Language", "en-us,en;q=0.5");
+        loginHeaders.put("Accept-Encoding", "gzip,deflate");
+        loginHeaders.put("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
+        loginHeaders.put("Keep-Alive", "300");
+        loginHeaders.put("Connection", "keep-alive");
+        loginHeaders.put("Referer", homepageURL);
+
+        isLoggedOn = false;
+        isCached = cached();
+    }
+
+    @BenchmarkOperation (
+        name    = "HomePage",
+        max90th = 1,
+        timing  = Timing.AUTO
+    )
+    public void doHomePage() throws IOException {
+        logger.finer("HomePage: Accessing " + homepageURL);
+
+        http.fetchURL(homepageURL);
+        imgBytes = 0;
+        imagesLoaded = 0;
+
+        StringBuilder responseBuffer = http.getResponseBuffer();
+        if (responseBuffer.length() == 0)
+            throw new IOException("Received empty response");
+
+        Set<String> images = parseImages(responseBuffer);
+        if (!isCached) {
+
+            // Fetch the CSS/JS files
+
+            loadStatics(homepageStatics);
+        }
+        loadImages(images);
+        selectedEvent = RandomUtil.randomEvent(random, responseBuffer);
+        logger.finer("Images loaded: " + imagesLoaded);
+        logger.finer("Image bytes loaded: " + imgBytes);
+        if (ctx.isTxSteadyState())
+            driverMetrics.homePageImages += images.size();
+            driverMetrics.homePageImagesLoaded += imagesLoaded;
+            driverMetrics.homePageImageBytes += imgBytes;
+    }
+
+    @BenchmarkOperation (
+        name    = "Login",
+        max90th = 1,
+        timing  = Timing.AUTO
+    )
+    public void doLogin() throws IOException, Exception {
+        logger.finer("In doLogin");
+        int randomId = 0; //use as password
+        username = null;
+
+        if (!isLoggedOn) {
+            randomId = selectUserID();
+            username = UserName.getUserName(randomId);
+            logger.fine("Logging in as " + username + ", " + randomId);
+            http.readURL(loginURL, constructLoginPost(randomId), loginHeaders);
+            // This redirects to home.
+            http.fetchURL(homepageURL);
+            int loginIdx = http.getResponseBuffer().indexOf("Login:");
+            if (loginIdx != -1)
+                throw new Exception(" Found login prompt at index " + loginIdx); 
+            
+            /*if (http.getResponseBuffer().indexOf("Login:") != 1216) {
+                logger.finest(http.getResponseBuffer().toString());
+                //throw new RuntimeException("Index of LOGIN = " +http.getResponseBuffer().indexOf("Login:") );
+                //logger.info(http.getResponseBuffer().toString());
+                throw new RuntimeException("Login as " + username + ", " +
+                                                        randomId + " failed.");
+            }*/
+            //logger.fine("Login successful as " + username + ", " + randomId);
+            isLoggedOn=true;
+        } else {
+            //already logged in --> logout,then log in again
+            doLogout();
+            doLogin();
+        }
+    }
+
+
+    @BenchmarkOperation (
+        name    = "Logout",
+        max90th = 1,
+        timing  = Timing.AUTO
+    )
+    public void doLogout() throws IOException {
+        if (isLoggedOn){
+            logger.finer("Logging off = " + isLoggedOn);
+            http.fetchURL(logoutURL);
+            cachedURLs.clear();
+            isCached = cached();
+            isLoggedOn=false;
+            http = new HttpTransport(); // clear all state
+        }
+    }
+
+
+    @BenchmarkOperation (
+        name    = "TagSearch",
+        max90th = 2,
+        timing  = Timing.AUTO
+    )
+    public void doTagSearch() throws IOException {
+        String tag = RandomUtil.randomTagName(random);
+        String search = tagSearchURL + "?tag=" + tag + "&submit=Search+Tags";
+        logger.finer("TagSearch: " + search);
+        http.fetchURL(search);
+        StringBuilder responseBuffer = http.getResponseBuffer();
+        if (responseBuffer.length() == 0)
+            throw new IOException("Received empty response");
+        Set<String> images = parseImages(responseBuffer);
+        loadStatics(tagSearchStatics);
+        loadImages(images);
+        String event = RandomUtil.randomEvent(random, responseBuffer);
+        if (event != null)
+            selectedEvent = event;
+        if (ctx.isTxSteadyState())
+            driverMetrics.tagSearchImages += images.size();
+    }
+
+    @BenchmarkOperation (
+        name    = "AddEvent",
+        max90th = 3,
+        timing  = Timing.MANUAL
+    )
+    public void doAddEvent() throws IOException {
+        logger.finer("doAddEvent");
+        ctx.recordTime();
+        http.readURL(addEventURL);
+        loadStatics(addEventStatics);
+
+        MultipartPostMethod post = new MultipartPostMethod(addEventResultURL);
+        if(isLoggedOn) {
+		    StringBuilder buffer = new StringBuilder(256);
+		    post.addParameter("event[title]", RandomUtil.randomText(random, 15, 20));
+		    post.addParameter("event[summary]", RandomUtil.randomText(random, 50, 200));
+            post.addParameter("event[description]", RandomUtil.randomText(random, 100, 495));
+            post.addParameter("event[telephone]", RandomUtil.randomPhone(random, buffer));
+            post.addParameter("event[event_timestamp(1i)]", "2008");
+            post.addParameter("event[event_timestamp(2i)]", "10");
+            post.addParameter("event[event_timestamp(3i)]", "20");
+            post.addParameter("event[event_timestamp(4i)]", "20");
+            post.addParameter("event[event_timestamp(5i)]", "10");
+
+            // We do the images last, not to split the fields into parts
+            post.addParameter("event[image]", eventImg);
+            post.addParameter("event[document]", eventPdf);
+            post.addParameter("tag_list", random.makeCString(4, 14));
+
+            addAddress(post);
+            
+            doMultiPartPost(post);
+        }
+        
+        ctx.recordTime();
+    }
+
+    @BenchmarkOperation (
+        name    = "AddPerson",
+        max90th = 3,
+        timing  = Timing.MANUAL
+    )
+    public void doAddPerson() throws IOException {
+        logger.finer("doAddPerson");
+        if (isLoggedOn)
+            doLogout();
+
+        ctx.recordTime();
+        http.readURL(addPersonURL);
+        loadStatics(addPersonStatics);
+
+        MultipartPostMethod post = new MultipartPostMethod(addPersonResultURL);
+        
+        String fields[]  = new String[8];
+        StringBuilder b = new StringBuilder(256);
+        int id = loadedUsers + personsAdded++ * ScaleFactors.activeUsers +
+                                                        ctx.getThreadId() + 1;
+        String username = UserName.getUserName(id);
+        if (username == null || username.length() == 0)
+            logger.warning("Username is null!");
+                            
+        post.addParameter("user[username]", username);
+        http.readURL(checkNameURL, "name=" + username);
+        
+        post.addParameter("user[password]", "" + id);
+        post.addParameter("user[password_confirmation]", "" + id);
+        post.addParameter("user[firstname]",  RandomUtil.randomName(random, b, 2, 12).toString());
+        b.setLength(0);
+        post.addParameter("user[lastname]",  RandomUtil.randomName(random, b, 5, 12).toString());
+        post.addParameter("user[email]", username + "@" + random.makeCString(3, 10) + ".com");
+        b.setLength(0);
+        post.addParameter("user[telephone]", RandomUtil.randomPhone(random, b).toString());
+        post.addParameter("user[summary]", RandomUtil.randomText(random, 50, 200));
+        post.addParameter("user[timezone]", RandomUtil.randomTimeZone(random));
+        
+        // Images
+        post.addParameter("user_image", personImg);        
+        
+        addAddress(post);
+        doMultiPartPost(post);
+        ctx.recordTime();
+    }
+
+    @BenchmarkOperation (
+        name    = "EventDetail",
+        max90th = 2,
+        timing  = Timing.AUTO
+    )
+    public void doEventDetail() throws IOException {
+        //select random event
+        logger.finer("doEventDetail");
+        if (selectedEvent == null) {
+            logger.warning("In event detail and select event is null");
+            http.fetchURL(homepageURL);
+            StringBuilder responseBuffer = http.getResponseBuffer();
+            selectedEvent = RandomUtil.randomEvent(random, responseBuffer);
+            if (selectedEvent == null) {
+                throw new IOException("In event detail and select event is null");
+            }    
+        }
+        
+        http.fetchURL(eventDetailURL + selectedEvent);
+        StringBuilder responseBuffer = http.getResponseBuffer();
+        if (responseBuffer.length() == 0)
+            throw new IOException("Received empty response");
+        boolean canAddAttendee = isLoggedOn &&
+                                responseBuffer.indexOf("Attend") != -1;
+        if (isLoggedOn && !canAddAttendee)
+           logger.warning("Logged on and can't attend");
+
+        Set<String> images = parseImages(responseBuffer);
+        loadStatics(eventDetailStatics);
+        loadImages(images);
+        if (canAddAttendee) {
+            // 10% of the time we can add ourselves, we will.
+            int card = random.random(0, 9);
+            if (card == 0) {
+                doAddAttendee();
+                if (ctx.isTxSteadyState())
+                    ++driverMetrics.addAttendeeCount;
+            }
+            if (ctx.isTxSteadyState())
+                ++driverMetrics.addAttendeeReadyCount;
+                driverMetrics.eventDetailImages += images.size();
+
+        }
+    }
+
+    @BenchmarkOperation (
+        name = "PersonDetail",
+        max90th = 2,
+        timing = Timing.AUTO
+    )
+    public void doPersonDetail() throws IOException {
+        logger.finer("doPersonDetail");
+        StringBuilder buffer = new StringBuilder(fileServiceURL.length() + 20);
+        //buffer.append(fileServiceURL).append("file=p");
+        
+        if (isLoggedOn) {
+            int id = random.random(1, ScaleFactors.users);
+            http.fetchURL(personDetailURL + id);
+            StringBuilder responseBuffer = http.getResponseBuffer();
+            if (responseBuffer.length() == 0)
+                throw new IOException("Received empty response");
+
+           // loadStatics(personStatics);
+           // for (String url : personGets)
+           //    http.readURL(url);
+
+            // http.readURL(buffer.append(id).append(".jpg").toString());
+
+            String event = RandomUtil.randomEvent(random, responseBuffer);
+            if (event != null)
+                selectedEvent = event;
+        }
+        else
+        {
+            // Need to handle this better. User profile is only for logged in users.
+            logger.warning("Trying to view user, but not logged in");
+            http.fetchURL(homepageURL);
+        }
+    }
+
+    public void doAddAttendee() throws IOException {
+        //can only add yourself (one attendee) to party
+        http.readURL(addAttendeeURL + selectedEvent + "/attend", "");
+        // http.readURL(updatePageURL, "list=attendees");
+    }
+
+    public Set<String> parseImages(StringBuilder buffer) {
+        LinkedHashSet<String> urlSet = new LinkedHashSet<String>();
+        String elStart = "<img ";
+        String attrStart = " src=\"";
+        int elStartLen = elStart.length() - 1; // Don't include the trailing space
+        int attrStartLen = attrStart.length();
+        int idx = 0;
+        logger.finest("Parsing images from buffer");
+        for (;;) {
+
+            // Find and copy out the element.
+            idx = buffer.indexOf(elStart, idx);
+            if (idx == -1)
+                break;
+            idx += elStartLen;
+            int endIdx = buffer.indexOf("/>", idx);
+            if (endIdx == -1)
+                break;
+            String elText = buffer.substring(idx, endIdx);
+            idx = endIdx + 1;
+
+            // Find the attribute
+            int idx2 = elText.indexOf(attrStart);
+            if (idx2 == -1) {
+                logger.finer("No img src attribute. Weird! " + elText);
+                continue;
+            }
+            endIdx = elText.indexOf("\"", idx2 + attrStartLen);
+            if (endIdx == -1) {
+                logger.warning("No img src attribute ending. Weird! " + elText);
+                continue;
+            }
+
+            String link = elText.substring(idx2 + attrStartLen, endIdx);
+            if (link.startsWith("fileService.")) {
+                String url = baseURL + '/' + link;
+
+                logger.finest("Adding " + url + " from idx " + idx);
+                urlSet.add(url);
+            }
+        }
+        return urlSet;
+    }
+
+    private void loadImages(Set<String> images) throws IOException {
+        if (images != null)
+            for (String image : images)
+                // Loads image only if not cached, means we can add to cache.
+                if (cachedURLs.add(image)) {
+                    logger.finer("Loading image " + image);
+                    imgBytes += http.readURL(image);
+                    ++imagesLoaded;
+                } else {
+                    logger.finer("Image already cached: Not loading " + image);
+                }
+    }
+
+    private boolean cached() {
+        // We have to decide whether the cache is empty or not.
+        // 40% of the time, it is empty.
+        boolean cached = true;
+        int selector = random.random(0, 9);
+        if (selector < 4) {
+            cached = false;
+        }
+        return cached;
+    }
+
+    private void loadStatics(String[] urls) throws IOException {
+
+        if (!isCached)
+            for (String url : urls)
+                if (cachedURLs.add(url)) {
+                    logger.finer("Loading URL " + url);
+                    http.readURL(url);
+                } else {
+                    logger.finer("URL already cached: Not loading " + url);
+                }
+    }
+
+    public DateFormat getDateFormat() {
+        if (df == null)
+            df = new SimpleDateFormat("yyyy-MM-dd");
+        return df;
+    }
+
+    public int selectUserID() {
+        return random.random(0,3) * ScaleFactors.activeUsers +
+                                                        ctx.getThreadId() + 1;
+    }
+
+
+    private String[] populateList(String[] arrList) {
+
+        String[] returnList = new String[arrList.length];
+        if (arrList != null) {
+
+            try {
+                for (int i = 0; i < arrList.length; i++) {
+                    returnList[i] = baseURL + arrList[i].trim();
+
+                }
+            } catch (Exception e) {
+                System.out.println ("Exception - " + e);
+                e.printStackTrace();
+            }
+        }
+        return returnList;
+    }
+
+    private String constructLoginPost(int randomId) {
+        return "users[username]=" + username + "&users[password]=" +
+                String.valueOf(randomId) + "&submit=Login";
+    }
+
+    public void doMultiPartPost(MultipartPostMethod post) throws IOException {
+
+        HttpClient client = new HttpClient();
+        client.setConnectionTimeout(5000);
+        int status = client.executeMethod(post);
+        if(status != HttpStatus.SC_OK)
+            throw new IOException("Multipart Post did not work");
+    }
+
+    public void addAddress(MultipartPostMethod post)
+    {
+        //add the address
+        post.addParameter("address[street1]", street1());
+        post.addParameter("address[street2]",street2());
+        post.addParameter("address[city]", random.makeCString(4, 14));
+        post.addParameter("address[state]", random.makeCString(2, 2).toUpperCase());
+        post.addParameter("address[zip]", random.makeNString(5, 5));
+        post.addParameter("address[country]", country());
+    }
+
+    public String street1() {
+        String[] STREETEXTS = { "Blvd", "Ave", "St", "Ln", "" };
+        StringBuilder buffer = new StringBuilder(255);
+        buffer.append(random.makeNString(1, 5)).append(' '); // number
+        RandomUtil.randomName(random, buffer, 1, 11); // street
+        String streetExt = STREETEXTS[random.random(0, STREETEXTS.length - 1)];
+        if (streetExt.length() > 0)
+            buffer.append(' ').append(streetExt);
+    	return buffer.toString();
+    }
+
+    public String street2() {
+        int toggle = random.random(0, 1); // street2
+        String street;
+        if (toggle > 0)
+          street = random.makeCString(5, 20);
+        else
+          street = "";
+        return street;
+    }
+
+    public String country() {
+        int toggle = random.random(0, 1);
+        StringBuilder buffer = new StringBuilder(255);
+        String cntry;
+        if (toggle == 0) {
+          cntry = "USA";
+        } else {
+          cntry = RandomUtil.randomName(random, buffer, 6, 16).toString();
+        }
+
+    return cntry;
+    }
+    
+    static class UIDriverMetrics implements CustomMetrics {
+
+        int addAttendeeCount = 0;
+        int addAttendeeReadyCount = 0;
+        int homePageImages = 0;
+        int tagSearchImages = 0;
+        int eventDetailImages = 0;
+        int homePageImagesLoaded = 0;
+        long homePageImageBytes = 0;
+
+        public void add(CustomMetrics other) {
+            UIDriverMetrics o = (UIDriverMetrics) other;
+            addAttendeeCount += o.addAttendeeCount;
+            addAttendeeReadyCount += o.addAttendeeReadyCount;
+            homePageImages += o.homePageImages;
+            tagSearchImages += o.tagSearchImages;
+            eventDetailImages += o.eventDetailImages;
+            homePageImageBytes += o.homePageImageBytes;
+            homePageImagesLoaded += o.homePageImagesLoaded;
+        }
+
+        public Element[] getResults() {
+            Result r = Result.getInstance();
+            int total = r.getOpsCountSteady("EventDetail");
+            Element[] el = new Element[7];
+            el[0] = new Element();
+            el[0].description = "% EventDetail views where attendee added";
+            el[0].target = "&gt;= 8";
+            if (total > 0) {
+                double pctAdd = 100d * addAttendeeCount / (double) total;
+                el[0].result = String.format("%.2f", pctAdd);
+                if (pctAdd >= 8d)
+                    el[0].passed = Boolean.TRUE;
+                else
+                    el[0].passed = Boolean.FALSE;
+            } else {
+                el[0].result = "";
+                el[0].passed = Boolean.FALSE;
+            }
+
+            el[1] = new Element();
+            el[1].description = "EventDetail count where attendee can be added";
+            el[1].result = String.valueOf(addAttendeeReadyCount);
+
+            int cnt = r.getOpsCountSteady("HomePage");
+            el[2] = new Element();
+            el[2].description = "Average images references on Home Page";
+            el[2].target = "10";
+            el[2].allowedDeviation = "0.5";
+            if (cnt > 0) {
+                double imagesPerPage = homePageImages / (double) cnt;
+                el[2].result = String.format("%.2f", imagesPerPage);
+                if (imagesPerPage >= 9.5d && imagesPerPage <= 10.5d)
+                    el[2].passed = Boolean.TRUE;
+                else
+                    el[2].passed = Boolean.FALSE;
+            } else {
+                el[2].result = "";
+                el[2].passed = Boolean.FALSE;
+            }
+
+            el[3] = new Element();
+            el[3].description = "Average images loaded per Home Page";
+            el[3].target = "&gt;= 4";
+            if (cnt > 0) {
+                double avgImgs = homePageImagesLoaded / (double) cnt;
+                el[3].result = String.format("%.2f", avgImgs);
+                if (avgImgs >= 4d)
+                    el[3].passed = Boolean.TRUE;
+                else
+                    el[3].passed = Boolean.FALSE;
+            } else {
+                el[3].result = "";
+                el[3].passed = Boolean.FALSE;
+            }
+
+            el[4] = new Element();
+            el[4].description = "Average image bytes received per Home Page";
+            el[4].target = "&gt;= 25000";
+            if (cnt > 0) {
+                double avgBytes = homePageImageBytes / (double) cnt;
+                el[4].result = String.format("%.2f", avgBytes);
+                if (avgBytes >= 20000)
+                    el[4].passed = Boolean.TRUE;
+                else
+                    el[4].passed = Boolean.FALSE;
+            } else {
+                el[4].result = "";
+                el[4].passed = Boolean.FALSE;
+            }
+            cnt = r.getOpsCountSteady("TagSearch");
+            el[5] = new Element();
+            el[5].description = "Average images on Tag Search Results";
+            el[5].target = "&gt;= 3";
+            if (cnt > 0) {
+                double avgImgs = tagSearchImages / (double) cnt;
+                el[5].result = String.format("%.2f", avgImgs);
+                if (avgImgs >= 3d)
+                    el[5].passed = Boolean.TRUE;
+                else
+                    el[5].passed = Boolean.FALSE;
+            } else {
+                el[5].result = "";
+                el[5].passed = Boolean.FALSE;
+            }
+            el[6] = new Element();
+            el[6].description = "Average images on Event Detail";
+            el[6].target = "&gt;= 9";
+            if (total > 0) {
+                double avgImgs = eventDetailImages / (double) total;
+                el[6].result = String.format("%.2f", avgImgs);
+                if (avgImgs >= 9d)
+                    el[6].passed = Boolean.TRUE;
+                else
+                    el[6].passed = Boolean.FALSE;
+            } else {
+                el[6].result = "";
+                el[6].passed = Boolean.FALSE;
+            }
+            return el;
+        }
+
+        public Object clone() {
+            UIDriverMetrics clone = new UIDriverMetrics();
+            clone.addAttendeeCount = addAttendeeCount;
+            clone.addAttendeeReadyCount = addAttendeeReadyCount;
+            clone.homePageImages = homePageImages;
+            clone.tagSearchImages = tagSearchImages;
+            clone.eventDetailImages = eventDetailImages;
+            clone.homePageImageBytes = homePageImageBytes;
+            clone.homePageImagesLoaded = homePageImagesLoaded;
+            return clone;
+        }
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/Web20Driver.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/Web20Driver.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/Web20Driver.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/Web20Driver.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,117 @@
+
+/* The contents of this file are subject to the terms
+ * of the Common Development and Distribution License
+ * (the License). You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://www.sun.com/cddl/cddl.html or
+ * install_dir/legal/LICENSE
+ * See the License for the specific language governing
+ * permission and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL
+ * Header Notice in each file and include the License file
+ * at install_dir/legal/LICENSE.
+ * If applicable, add the following below the CDDL Header,
+ * with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * $Id: Web20Driver.java,v 1.1 2007/02/21 23:54:59 sp208304 Exp $
+ *
+ * Copyright 2005 Sun Microsystems Inc. All Rights Reserved
+ */
+package com.sun.web20.driver;
+
+import com.sun.faban.driver.*;
+import com.sun.faban.driver.util.Random;
+
+import javax.xml.xpath.XPathExpressionException;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+@BenchmarkDefinition (
+    name    = "Web 2.0 workload",
+    version = "0.2"
+)
+@BenchmarkDriver (
+    name           = "Web20Driver",
+    threadPerScale    = 1
+)
+/* @MatrixMix (
+    operations = {"MyOperation1", "MyOperation2"},
+    mix = { @Row({  0, 70}), 
+            @Row({ 60,  0}) },
+    deviation = 2
+)
+ */
+@FlatMix (
+    operations = {"HomePage", "SubmitPage"},
+    mix = { 50, 50 },
+    deviation = 2    
+)
+@NegativeExponential (
+    cycleType = CycleType.CYCLETIME,
+    cycleMean = 5000,
+    cycleDeviation = 2
+)
+public class Web20Driver {
+
+    /** The driver context for this instance */
+    private DriverContext ctx;
+    private HttpTransport http;
+    private String url1, url2;
+    Logger logger;
+    Random random;
+
+    public Web20Driver() throws XPathExpressionException {
+        ctx = DriverContext.getContext();
+        http = new HttpTransport();
+        logger = ctx.getLogger();
+        random = ctx.getRandom();
+        String host = ctx.getXPathValue("/webBenchmark/serverConfig/host");
+        String port = ctx.getXPathValue("/webBenchmark/serverConfig/port");
+        String path1 = ctx.getProperty("path1");
+        String path2 = ctx.getProperty("path2");
+        url1 = "http://" + host + ':' + port + '/' + path1;
+        url2 = "http://" + host + ':' + port + '/' + path2;
+  
+    }
+
+    @OnceBefore public void testPreRun() {
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+        }
+        logger.info("Tested pre-run (sleep 5) done");
+    }
+
+    @OnceAfter public void testPostRun() {
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+        }
+        logger.info("Tested post-run (sleep 5) done");
+    }
+
+    @BenchmarkOperation (
+        name    = "HomePage",
+        max90th = 2,
+        timing  = Timing.AUTO
+    )
+    public void doMyOperation1() throws IOException {
+        logger.finest("Accessing " + url1);
+        http.fetchURL(url1);
+    }
+
+    @BenchmarkOperation (
+        name    = "SubmitPage",
+        max90th = 2,
+        timing  = Timing.AUTO
+    )
+    public void doMyOperation2() throws IOException {
+        logger.finest("Accessing " + url2);
+        http.fetchURL(url2);
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/fsloader/FileLoader.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/fsloader/FileLoader.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/fsloader/FileLoader.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/fsloader/FileLoader.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,63 @@
+package com.sun.web20.fsloader;
+
+import com.sun.web20.util.ScaleFactors;
+
+import java.nio.channels.FileChannel;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+
+public class FileLoader {
+
+    public static void main(String[] args) throws Exception {
+        String srcDir = args[0];
+        ScaleFactors.setActiveUsers(Integer.parseInt(args[1]));
+        srcDir += File.separator;
+        FileChannel img = new FileInputStream(
+                                    srcDir + "person.jpg").getChannel();
+        FileChannel thumb = new FileInputStream(
+                                    srcDir + "person_thumb.jpg").getChannel();
+        long imgSize = img.size();
+        long thumbSize = thumb.size();
+
+        for (int i = 1; i <= ScaleFactors.users; i++) {
+            System.out.println("Loading files for user " + i);
+            copyTo(img, imgSize, "p" + i + ".jpg");
+            copyTo(thumb, thumbSize, "p" + i + "t.jpg");
+        }
+
+        img.close();
+        thumb.close();
+
+
+        img = new FileInputStream(srcDir + "event.jpg").getChannel();
+        thumb = new FileInputStream(srcDir + "event_thumb.jpg").getChannel();
+        FileChannel lit = new FileInputStream(
+                                    srcDir + "event.pdf").getChannel();
+
+        imgSize = img.size();
+        thumbSize = thumb.size();
+        long litSize = lit.size();
+
+        for (int i = 1; i <= ScaleFactors.events; i++) {
+            System.out.println("Loading files for event " + i);
+            copyTo(img, imgSize, "e" + i + ".jpg");
+            copyTo(thumb, thumbSize, "e" + i + "t.jpg");
+            copyTo(lit, litSize, "e" + i + ".pdf");
+        }
+
+        img.close();
+        thumb.close();
+        lit.close();
+        System.exit(0);
+    }
+
+    private static void copyTo(FileChannel src, long size, String destFile)
+            throws IOException {
+        FileChannel dest = (new FileOutputStream(destFile)).getChannel();
+        src.transferTo(0, size, dest);
+        dest.close();
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/harness/Web20Benchmark.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/harness/Web20Benchmark.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/harness/Web20Benchmark.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/harness/Web20Benchmark.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,298 @@
+
+/* The contents of this file are subject to the terms
+ * of the Common Development and Distribution License
+ * (the License). You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://www.sun.com/cddl/cddl.html or
+ * install_dir/legal/LICENSE
+ * See the License for the specific language governing
+ * permission and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL
+ * Header Notice in each file and include the License file
+ * at install_dir/legal/LICENSE.
+ * If applicable, add the following below the CDDL Header,
+ * with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * $Id: Web20Benchmark.java,v 1.27 2008/03/20 22:31:40 akara Exp $
+ *
+ * Copyright 2005 Sun Microsystems Inc. All Rights Reserved
+ */
+package com.sun.web20.harness;
+
+import com.sun.faban.common.Command;
+import com.sun.faban.common.CommandHandle;
+import com.sun.faban.common.NameValuePair;
+import com.sun.faban.harness.DefaultFabanBenchmark;
+import com.sun.faban.harness.RunContext;
+import com.sun.faban.harness.engine.ApacheHttpdService;
+import com.sun.faban.harness.engine.LighttpdService;
+import com.sun.faban.harness.engine.MemcachedService;
+
+import com.sun.faban.harness.engine.WebServerService;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static com.sun.faban.harness.RunContext.*;
+
+/**
+ * Harness hook for the sample web benchmark. This class is not needed
+ * for benchmarks implemented using the Faban Driver Framework if the
+ * default behavior is sufficient. We just show the hooks you can
+ * customize in this class. If the default behavior is desired, you can
+ * leave out the benchmark-class element in benchmark.xml.
+ *
+ * @author Akara Sucharitakul
+ */
+public class Web20Benchmark extends DefaultFabanBenchmark {
+    
+    static Logger logger = Logger.getLogger(
+                                        Web20Benchmark.class.getName());
+    int totalRunningTimeInSecs = 0;
+    private LinkedHashSet<String> hostsSet;
+    private ArrayList<NameValuePair<Integer>> hostsPorts;    
+    private String webServerBinPath, webServerLogPath, webServerConfPath;
+    private String webServerPidPath, phpIniPath, cacheBinPath, dbConfPath;
+    WebServerService webServerService;
+    MemcachedService memcachedService = MemcachedService.getHandle();
+
+    /**
+     * Allows benchmark to validate the configuration file. Note that no
+     * execution facility is available during validation.
+     *
+     * @throws Exception if any error occurred.
+     * @see com.sun.faban.harness.RunContext#exec(com.sun.faban.common.Command)
+     */
+    public void validate() throws Exception {
+        params = getParamRepository();
+        params.setParameter("fa:runConfig/fd:driverConfig" +
+                "[@name='UIDriver']/fd:properties/fd:property" +
+                "[@name='resourcePath']",
+                getBenchmarkDir() + "resources" + File.separator);
+
+        //cache servers get list of servers for the host
+        String cacheServers = params.getParameter("cacheServers/serverList");
+
+        // replacing all the newline characters and other white space
+        // characters with a blank space
+        cacheServers = cacheServers.replaceAll("\\s", " ");
+
+        // Find the patterns that have either hostname or hostname:port values
+        Pattern p1 = Pattern.compile("([a-zA-Z_0-9-\\.]+):?(\\w*)\\s*");
+        Matcher m1 = p1.matcher(cacheServers + ' '); // add a whitespace at end
+
+        hostsSet = new LinkedHashSet<String>();
+        hostsPorts = new ArrayList<NameValuePair<Integer>>();
+
+        //need to get these data structures for restarting memcache servers for RunContext
+
+        //  Fill up the hosts set with names of all the hosts
+        for (boolean found = m1.find(); found; found = m1.find()) {
+            NameValuePair<Integer> hostPort = new NameValuePair<Integer>();
+            hostPort.name = m1.group(1);
+            String port = m1.group(2);
+            if (port != null && port.length() > 1)
+                hostPort.value = new Integer(port);
+            else
+                hostPort.value = 11211;
+            //logger.info("with port number " + hostPort.value);
+            hostsSet.add(hostPort.name);
+            hostsPorts.add(hostPort);
+        }
+
+        // Now extract the unique hosts
+        StringBuffer hosts = new StringBuffer();
+        for (String host : hostsSet) {
+            hosts.append(host);
+            hosts.append(' ');
+        }
+
+        // Update the unique hosts to the host filed and save
+        String cacheHosts = hosts.toString().trim();
+        params.setParameter("cacheServers/fa:hostConfig/fa:host", cacheHosts);
+        logger.info("Memcached Hosts: " + cacheHosts);
+
+        params.save();
+        super.validate();
+
+    }
+
+    /**
+     * This method is called to configure the specific benchmark run
+     * Tasks done in this method include reading user parameters,
+     * logging them and initializing various local variables.
+     *
+     * @throws Exception If configuration was not successful
+     */
+    public void configure() throws Exception {
+        
+        //Obtaining configuration parameters
+        String webserverType = params.getParameter("webServer/type");
+ 
+        webServerBinPath = params.getParameter("webServer/hostBinPath");
+        webServerLogPath = params.getParameter("webServer/hostLogPath");
+        webServerConfPath = params.getParameter("webServer/hostConfPath");
+        webServerPidPath = params.getParameter("webServer/hostPidPath");
+        phpIniPath = params.getParameter("webServer/phpIniPath");
+        cacheBinPath = params.getParameter("cacheServers/cacheBinPath");
+        dbConfPath = params.getParameter("dbServer/dbConfPath");
+        String dbhost = params.getParameter("dbServer/fa:hostConfig/fa:host");
+        String webhost = params.getParameter("webServer/fa:hostConfig/fa:host");
+        /*
+       if (webserverType.equals("apache")) {
+            webServerService = ApacheHttpdService.getHandle();                           
+            RunContext.getFile(webhost, webServerConfPath +
+                    File.separator + "httpd.conf",
+                            RunContext.getOutDir() + "httpd.conf." + webhost);
+       } else {
+            webServerService = LighttpdService.getHandle();
+            RunContext.getFile(webhost, webServerConfPath + 
+                    File.separator + "lighttpd.conf",
+                            RunContext.getOutDir() + "lighttpd.conf." + webhost);
+       }
+       */
+        /* RunContext.getFile(webhost, phpIniPath + "/php.ini",
+                            RunContext.getOutDir() + "php.ini." + webhost);
+
+        RunContext.getFile(dbhost, dbConfPath + "/my.cnf",
+                RunContext.getOutDir() + "my.cnf." + dbhost);
+        */
+
+        // Reloading database and media as necessary.
+        boolean reloadDB = Boolean.parseBoolean(
+                params.getParameter("dbServer/reloadDB"));
+        boolean reloadMedia = Boolean.parseBoolean(
+                params.getParameter("dataStorage/reloadMedia"));
+
+        int scale = -1;
+        if (reloadDB || reloadMedia)
+            scale =Integer.parseInt(params.getParameter("dbServer/scale"));
+
+        CommandHandle dbHandle = null;
+        CommandHandle mediaHandle = null;
+        if (reloadDB) {
+            String dbHost =
+                    params.getParameter("dbServer/fa:hostConfig/fa:host");
+            String driver = params.getParameter("dbServer/dbDriver");
+            String connectURL = params.getParameter("dbServer/connectURL");
+            // Un-escape the URL.
+            connectURL = connectURL.replace("&amp;", "&");
+            Command c = new Command("-Dcommit.tx=false " +
+                                    "com.sun.web20.loader.LoadController " +
+                                    driver + ' ' + connectURL + ' ' + scale);
+            c.setSynchronous(false);
+            dbHandle = java(dbHost, c);
+        }
+
+        if (reloadMedia) {
+            String mediaHost = params.getParameter(
+                                        "dataStorage/fa:hostConfig/fa:host");
+            Command c = new Command("loader.pl -d sfbay.sun.com -s " + scale);
+            c.setSynchronous(false);
+            c.setStreamHandling(Command.STDOUT, Command.TRICKLE_LOG);
+            c.setStreamHandling(Command.STDERR, Command.TRICKLE_LOG);            
+            mediaHandle = exec(mediaHost, c);
+        }
+        
+        if (dbHandle != null)
+            dbHandle.waitFor();
+        
+        if (mediaHandle != null)
+            mediaHandle.waitFor();
+
+        //start the memcache servers
+        /*int index = 0;
+        String memServers[] = new String[hostsPorts.size()];
+        int ports[] = new int[hostsPorts.size()];
+        for (NameValuePair<Integer> thisCacheServer : hostsPorts) {
+            memServers[index] = thisCacheServer.name;
+            ports[index++] = thisCacheServer.value;
+        } 
+        memcachedService.setup(memServers, ports, "-u mysql -m 256",
+                cacheBinPath);
+        if ( !memcachedService.restartServers())
+            throw (new Exception("Memcached server(s) restart failed"));
+        
+        
+        // Now start the web servers
+        String ahosts[] = new String[1];
+        ahosts[0] = webhost;
+        webServerService.setup(ahosts, webServerBinPath, webServerLogPath, 
+                webServerConfPath, webServerPidPath);
+        if ( !webServerService.restartServers())
+            throw (new Exception("Webserver(s) restart failed"));
+        */
+        super.configure();
+    }
+
+     /**
+      * override DefaultBenchmark's start method so memcache stats can be
+      * collected via the Web20benchmark harness class
+      */
+    public void start() throws Exception {
+
+         //get the server list
+         String cacheServers = params.getParameter("cacheServers/serverList");
+         String[] cacheHosts = params.getTokenizedValue(
+                                        "cacheServers/fa:hostConfig/fa:host");
+         String rampUp = params.getParameter(
+                                "fa:runConfig/fa:runControl/fa:rampUp");
+         String steadyState = params.getParameter(
+                                "fa:runConfig/fa:runControl/fa:steadyState");
+         String rampDown = params.getParameter(
+                                "fa:runConfig/fa:runControl/fa:rampDown");
+         String interval = params.getParameter("fa:runConfig/" +
+                 "fd:driverConfig[@name='UIDriver']/fd:stats/fd:interval");
+
+
+         //calculate total running time, including rampUp, steadyState,
+         // and rampDown
+         this.totalRunningTimeInSecs = Integer.parseInt(rampUp) +
+                 Integer.parseInt(steadyState) + Integer.parseInt(rampDown);
+
+//         Command statsCommand = new Command(
+//                 "com.sun.web20.util.MemCacheUtility " + cacheServers + " -s "
+//                 + rampUp + " -e " + steadyState + " -i " + interval);
+//         statsCommand.setSynchronous(false);
+//         statsCommand.setStreamHandling(Command.STDOUT, Command.CAPTURE);
+//         statsCommand.setOutputFile(Command.STDOUT,  RunContext.getOutDir() +
+//                 "memcachestats.log." + getHostName(cacheHosts[0]));
+         // Use the real name of the first host.
+
+         super.start();
+
+//         logger.info("Launching memcache stats collection with " +
+//                        "interval time of " + interval);
+//         RunContext.java(statsCommand);
+     }
+    
+    /* override DefaultBenchmark's end method to collect apache log file
+     * via the Web20Benchmark harness class
+     */
+    
+    public void end () throws Exception {
+     
+        super.end();
+        
+        //stop the memcached servers
+        //logger.info("Stopping Memcached servers");
+        //memcachedService.stopServers();
+        
+        // xfer apache logs
+        //logger.info("Transferring Apache error logs");
+        //webServerService.xferLogs(totalRunningTimeInSecs);
+   
+        // stop apache servers
+        //logger.info("Stopping Apache servers");
+        //webServerService.stopServers();
+    }
+    
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Address.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Address.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Address.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Address.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,82 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.RandomUtil;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ * Address loader.
+ */
+public class Address extends Loadable {
+
+    private static final String STATEMENT = "insert into addresses (street1, " +
+            "street2, city, state, zip, country, latitude, longitude)" +
+            "values (?, ?, ?, ?, ?, ?, ?, ?)";
+    public static final String[] STREETEXTS = { "Blvd", "Ave", "St", "Ln", "" };
+    static Logger logger = Logger.getLogger(Address.class.getName());
+
+    String[] fields = new String[8];
+
+    public String getClearStatement() {
+        return "truncate table addresses";
+    }
+    
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        StringBuilder buffer = tr.getBuffer();
+        buffer.append(r.makeNString(1, 5)).append(' '); // number
+        RandomUtil.randomName(r, buffer, 1, 11); // street
+        String streetExt = STREETEXTS[r.random(0, STREETEXTS.length - 1)];
+        if (streetExt.length() > 0)
+            buffer.append(' ').append(streetExt);
+
+        fields[0] = buffer.toString();
+
+        int toggle = r.random(0, 1); // street2
+        if (toggle > 0)
+            fields[1] = r.makeCString(5, 20);
+
+        fields[2] = r.makeCString(4, 14); // city
+        fields[3] = r.makeCString(2, 2).toUpperCase(); // state
+        fields[4] = r.makeNString(5, 5);  // zip
+
+        toggle = r.random(0, 1);
+        if (toggle == 0) {
+            fields[5] = "USA";
+        } else {
+            buffer.setLength(0);
+            fields[5] = RandomUtil.randomName(r, buffer, 6, 16).toString();
+        }
+        // Latitude, we do not get addresses in polar circles. So the limit
+        fields[6] = String.format("%.6f", r.drandom(-66.560556d, 66.560556d));
+
+        fields[7] = String.format("%.6f", r.drandom(-179.999999d, 180d));
+    }
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            PreparedStatement s = c.prepareStatement(STATEMENT);
+            int i;
+            for (i = 0; i < fields.length; i++)
+            {
+                if (fields[i] != null)
+                    s.setString(i + 1, fields[i]);
+                else
+                    s.setNull(i + 1, Types.VARCHAR);
+            }
+            c.addBatch();
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Attendees.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Attendees.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Attendees.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Attendees.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,62 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.util.UserName;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.LinkedHashSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Attendees Loader
+ */
+public class Attendees extends Loadable {
+    // We use on average of 55 attendees per event. Random 10..100 Attendees.
+
+    private static final String STATEMENT = "insert into " +
+            "events_users" +
+            "(user_id, event_id) values (?, ?)";
+
+    static Logger logger = Logger.getLogger(Attendees.class.getName());
+
+    int eventId;
+    LinkedHashSet<Integer> userIdSet;
+
+    public String getClearStatement() {
+        return "truncate table events_users";
+    }
+
+    public Attendees(int eventId) {
+        this.eventId = ++eventId;
+    }
+
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        int attendees = r.random(10, 100);
+        userIdSet = new LinkedHashSet<Integer>(attendees);
+        for (int i = 0; i <attendees; i++)
+            while(!userIdSet.add(r.random(1, ScaleFactors.users)));
+    }
+
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            for (int userId : userIdSet) {
+                PreparedStatement s = c.prepareStatement(STATEMENT);
+                s.setInt(1, userId);
+                s.setInt(2, eventId);
+                c.addBatch();
+            }
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Comments.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Comments.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Comments.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Comments.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,78 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.util.UserName;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.sql.Date;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Comments Loader.
+ */
+public class Comments extends Loadable {
+    // We use on average of 10 comments per event. Random 0..20 comments..
+
+    public static final Date BASE_DATE = new Date(System.currentTimeMillis());
+    private static final String STATEMENT = "insert into comments " +
+            "(user_id, event_id, comment, rating, id, created_at, updated_at) values (?, ?, ?, ?, ?, ?, ?)";
+
+    static Logger logger = Logger.getLogger(Comments.class.getName());
+
+    int eventId, commentId;
+    int[] users;
+    String[] comments;
+    int[] ratings;
+    Date createdTimestamp;
+
+    public Comments(int eventId) {
+        this.eventId = ++eventId;
+    }
+
+    public String getClearStatement() {
+        return "truncate table comments";
+    }
+
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        int commentCount = r.random(0, 20);
+        users = new int[commentCount];
+        comments = new String[commentCount];
+        ratings = new int[commentCount];
+        for (int i = 0; i < users.length; i++) {
+            users[i] = r.random(1, ScaleFactors.users);;
+            comments[i] = r.makeCString(10, 1000);
+            ratings[i] = r.random(2, 5);
+        }
+        createdTimestamp = r.makeDateInInterval( //createdtimestamp
+                BASE_DATE, -540, 0);
+    }
+
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            for (int i = 0; i < users.length; i++) {
+                PreparedStatement s = c.prepareStatement(STATEMENT);
+                s.setInt(1, users[i]);
+                s.setInt(2, eventId);
+                s.setString(3, comments[i]);
+                s.setInt(4, ratings[i]);
+                s.setInt(5, eventId * 20 + i);
+                s.setDate(6, createdTimestamp);
+                s.setDate(7, createdTimestamp);
+                c.addBatch();
+            }
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Documents.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Documents.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Documents.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Documents.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,55 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.util.UserName;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Comments Loader.
+ */
+public class Documents extends Loadable {
+    // We use on average of 10 comments per event. Random 0..20 comments..
+
+    private static final String STATEMENT = "insert into documents " +
+            "(size, content_type, filename, id) " + 
+            "values (?, ?, ?, ?)";
+
+    static Logger logger = Logger.getLogger(Comments.class.getName());
+
+    int eventId;
+
+    public Documents(int eventId) {
+        this.eventId = ++eventId;
+    }
+
+    public String getClearStatement() {
+        return "truncate table documents";
+    }
+
+    public void prepare() {
+    }
+
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            PreparedStatement s = c.prepareStatement(STATEMENT);
+            s.setInt(1, 129585);
+            s.setString(2, "application/pdf");
+            s.setString(3, "e" + eventId + "l.pdf");
+            s.setInt(4, this.eventId);
+            c.addBatch();
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/EventTag.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/EventTag.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/EventTag.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/EventTag.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,68 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.RandomUtil;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.util.LinkedHashSet;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * The Tag-Event relationship loader.
+ */
+public class EventTag extends Loadable{
+
+    // We use on average of 3.5 tags per event. Random 1..6 tags.
+    // Once we know the tag count, we have to select tags.
+
+    private static final String STATEMENT = "insert into " +
+            "taggings " +
+            "(tag_id, taggable_id, taggable_type) values (?, ?, 'Event')";
+
+    static Logger logger = Logger.getLogger(EventTag.class.getName());
+
+    int eventId;
+    int [] tagIds;
+
+    public EventTag(int eventId) {
+        this.eventId = ++eventId;
+    }
+
+    public String getClearStatement() {
+        return "truncate table taggings";
+    }
+
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        int numTags = r.random(1, 7); // Avg is 4 tags per event
+        LinkedHashSet<Integer> tagSet = new LinkedHashSet<Integer>(numTags);
+        for (int i = 0; i < numTags; i++)
+            while (!tagSet.add(RandomUtil.randomTagId(r, 0.1d)));
+
+        tagIds = new int[tagSet.size()];
+        int idx = 0;
+        for (int tagId : tagSet)
+            tagIds[idx++] = tagId;
+    }
+
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            for (int tagId : tagIds) {
+                PreparedStatement s = c.prepareStatement(STATEMENT);
+                s.setInt(1, tagId);
+                s.setInt(2, eventId);
+                c.addBatch();
+            }
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Friends.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Friends.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Friends.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Friends.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,70 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.util.UserName;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.util.LinkedHashSet;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Friends loader
+ */
+public class Friends extends Loadable {
+    // We use on average of 15 friends. Random 2..28 Friends.
+
+    private static final String STATEMENT = "insert into invites " +
+            "(user_id, user_id_target, is_accepted) values (?, ?, 1)";
+
+    static Logger logger = Logger.getLogger(Friends.class.getName());
+
+    int id;
+    int[] friends;
+
+    public Friends(int id) {
+        this.id = ++id;
+    }
+
+    public String getClearStatement() {
+        return "truncate table invites";
+    }
+
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        int count = r.random(2, 28);
+
+        LinkedHashSet<Integer> friendSet = new LinkedHashSet<Integer>(count);
+        for (int i = 0; i < count; i++) {
+            int friendId;
+            do { // Prevent friend to be the same user.
+                friendId = r.random(1, ScaleFactors.users);
+            } while (friendId == id || !friendSet.add(friendId));
+        }
+
+        friends = new int[friendSet.size()];
+        int idx = 0;
+        for (int friendId : friendSet)
+            friends[idx++] = friendId;
+    }
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            for (int friend : friends) {
+                PreparedStatement s = c.prepareStatement(STATEMENT);
+                s.setInt(1, id);
+                s.setInt(2, friend);
+                c.addBatch();
+            }
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Images.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Images.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Images.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Images.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,60 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.util.UserName;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Comments Loader.
+ */
+public class Images extends Loadable {
+    // We use on average of 10 comments per event. Random 0..20 comments..
+
+    private static final String STATEMENT = "insert into images " +
+            "(size, content_type, filename, height, width, thumbnail, id) " + 
+            "values (?, ?, ?, ?, ?, ?, ?)";
+
+    static Logger logger = Logger.getLogger(Comments.class.getName());
+
+    int eventId;
+    String prefix;
+
+    public Images(int eventId, String prefix) {
+        this.eventId = ++eventId;
+        this.prefix = prefix;
+    }
+
+    public String getClearStatement() {
+        return "truncate table images";
+    }
+
+    public void prepare() {
+    }
+
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            PreparedStatement s = c.prepareStatement(STATEMENT);
+            s.setInt(1, 671614);
+            s.setString(2, "application/jpg");
+            s.setString(3, prefix + eventId + ".jpg");
+            s.setInt(4, 1280);
+            s.setInt(5, 960);
+            s.setString(6, prefix + eventId + "t.jpg");
+            s.setInt(7, this.eventId);
+            c.addBatch();
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/LoadController.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/LoadController.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/LoadController.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/LoadController.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,72 @@
+package com.sun.web20.loader;
+
+import com.sun.web20.util.ScaleFactors;
+
+import java.util.logging.Logger;
+
+import static com.sun.web20.loader.framework.Loader.*;
+
+public class LoadController {
+
+    static Logger logger = Logger.getLogger(LoadController.class.getName());
+
+    public static void main(String[] args) throws Exception {
+        setJDBCDriverClassName(args[0]);
+        setConnectionURL(args[1]);
+        ScaleFactors.setActiveUsers(Integer.parseInt(args[2]));
+
+        // Clear the database
+        logger.info("Clearing database tables.");
+        clear(new Person(0, 0));
+        clear(new Friends(0));
+        clear(new Address());
+        clear(new Tag(0));
+        clear(new SocialEvent(0));
+        clear(new EventTag(0));
+        clear(new Attendees(0));
+        clear(new Comments(0));
+        clear(new Documents(0));
+        clear(new Images(0, ""));
+
+        // load person, friends, and addresses
+        logger.info("Creating persons, friends, and addresses.");
+        for (int i = 0; i < ScaleFactors.users; i++) {
+            int imageId = ScaleFactors.events + i + 1;
+            load(new Person(i, imageId));
+            load(new Friends(i));
+            load(new Address());
+            load(new Images(imageId, "p"));
+        }
+
+        // load tags
+        logger.info("Creating tags.");
+        for (int i = 0; i < ScaleFactors.tagCount; i++) {
+            load(new Tag(i));
+        }
+
+        // load events and all relationships to events
+        logger.info("Creating events, attendees, comments.");
+        for (int i = 0; i < ScaleFactors.events; i++) {
+            load(new SocialEvent(i));
+            load(new Documents(i));
+            load(new Images(i, "e"));
+            load(new EventTag(i));
+            load(new Attendees(i));
+            load(new Comments(i));
+        }
+
+        waitProcessing();
+        logger.info("Done data creation.");
+
+        // Now we need to check that all loading is done.
+        shutdown();
+        logger.info("Done data loading.");
+
+        // We use a new set of connections and thread pools for postLoad.
+        // This is to ensure all load tasks are done before this one starts.
+        postLoad(new Tag(0));
+        shutdown();
+        logger.info("Done post-load.");
+        System.exit(0); // Signal successful loading.
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Person.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Person.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Person.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/Person.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,75 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.UserName;
+import com.sun.web20.util.RandomUtil;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * Person loader
+ */
+public class Person extends Loadable {
+
+    private static final String STATEMENT = "insert into users (username, " +
+            "password, firstname, lastname, email, telephone, " +
+            "summary, timezone, address_id, image_id, id, thumbnail)" +
+            "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+    static Logger logger = Logger.getLogger(Person.class.getName());
+
+    int id;
+    String[] fields = new String[10];
+    int addressId, thumbnail, imageId;
+
+    public Person(int id, int imageId) {
+        this.id = ++id;
+        this.imageId = imageId;
+    }
+
+    public String getClearStatement() {
+        return "truncate table users";
+    }
+
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        StringBuilder b = tr.getBuffer();
+        fields[0] = UserName.getUserName(id);
+        fields[1] = String.valueOf(id);
+        fields[2] = RandomUtil.randomName(r, b, 2, 12).toString();
+        b.setLength(0);
+        fields[3] = RandomUtil.randomName(r, b, 5, 15).toString();
+        fields[4] = r.makeCString(3, 10);
+        fields[4] = fields[2] + '_' + fields[3] + '@' + fields[4] + ".com";
+        b.setLength(0);
+        fields[5] = RandomUtil.randomPhone(r, b);
+        fields[6] = RandomUtil.randomText(r, 250, 2500);
+        fields[7] = "PST";
+        addressId = r.random(1, ScaleFactors.users);
+        thumbnail = imageId;
+    }
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            PreparedStatement s = c.prepareStatement(STATEMENT);
+            for (int i = 0; i < fields.length; i++)
+                s.setString(i + 1, fields[i]);
+            s.setInt(9, addressId);
+            s.setInt(10, imageId);
+            s.setInt(11, id);
+            s.setInt(12, thumbnail);
+            c.addBatch();
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+}

Added: incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/SocialEvent.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/SocialEvent.java?rev=706345&view=auto
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/SocialEvent.java (added)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/loader/SocialEvent.java Mon Oct 20 10:39:16 2008
@@ -0,0 +1,98 @@
+package com.sun.web20.loader;
+
+import com.sun.faban.driver.util.Random;
+import com.sun.web20.util.UserName;
+import com.sun.web20.util.RandomUtil;
+import com.sun.web20.util.ScaleFactors;
+import com.sun.web20.loader.framework.Loadable;
+import com.sun.web20.loader.framework.ThreadConnection;
+import com.sun.web20.loader.framework.ThreadResource;
+
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.text.DateFormat;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * SocialEvent loader.
+ */
+public class SocialEvent extends Loadable {
+
+    public static final Date BASE_DATE = new Date(System.currentTimeMillis());
+
+    private static final String STATEMENT = "insert into events " +
+            "(title, description, telephone, " +
+            "event_timestamp, event_date, summary, created_at, address_id, " +
+            "total_score, num_votes, disabled, user_id, image_id, document_id) " +
+            "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+    private static final String[] EVT_MINUTES = { "00", "15", "30", "45" };
+
+    static Logger logger = Logger.getLogger(SocialEvent.class.getName());
+    int id;
+
+    String[] fields = new String[6];
+    Date createdTimestamp;
+    int[] ifields = new int[7];
+
+    public SocialEvent(int id) {
+        this.id = ++id;
+    }
+
+    public String getClearStatement() {
+        return "truncate table events";
+    }
+
+    public void prepare() {
+        ThreadResource tr = ThreadResource.getInstance();
+        Random r = tr.getRandom();
+        StringBuilder buffer = tr.getBuffer();
+        fields[0] = RandomUtil.randomText(r, 15, 20); //title
+        fields[1] = RandomUtil.randomText(r, 50, 495); // description
+        fields[2] = RandomUtil.randomPhone(r, buffer); //phone
+        DateFormat dateFormat = tr.getDateFormat(); // eventtimestamp
+        String eventDate = dateFormat.format(
+                    r.makeDateInInterval(BASE_DATE, 0, 540));
+                    
+        int eventHr = r.random(7, 21);
+        String eventMin = EVT_MINUTES[r.random(0, 3)];  // eventtimestamp
+        fields[3] = String.format("%s %02d:%s:00",
+                                            eventDate, eventHr, eventMin);
+        fields[4] = eventDate; // eventdate
+        fields[5] = RandomUtil.randomText(r, 25, 99); // summary
+        
+        createdTimestamp = r.makeDateInInterval( //createdtimestamp
+                BASE_DATE, -540, 0);
+        
+        ifields[0] = r.random(1, ScaleFactors.users);
+        ifields[1] = 0;
+        ifields[2] = 0;
+        ifields[3] = 1;
+        ifields[4] = r.random(1, ScaleFactors.users);
+        ifields[5] = id;
+        ifields[6] = id;
+
+        // The rest is initialized to 0 anyway, leave it that way.
+    }
+
+    public void load() {
+        ThreadConnection c = ThreadConnection.getInstance();
+        try {
+            PreparedStatement s = c.prepareStatement(STATEMENT);
+            for (int i = 0; i < fields.length; i++)
+                if (fields[i] != null)
+                    s.setString(i + 1, fields[i]);
+                else
+                    s.setNull(i + 1, Types.VARCHAR);
+            s.setDate(7, createdTimestamp);
+            for (int i = 0; i < ifields.length; i++)
+                s.setInt(8 + i, ifields[i]);
+            c.addBatch();
+        } catch (SQLException e) {
+            logger.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+}