com.couchbase.roadrunner.workloads.Workload.java Source code

Java tutorial

Introduction

Here is the source code for com.couchbase.roadrunner.workloads.Workload.java

Source

/**
 * Copyright (C) 2009-2013 Couchbase, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING
 * IN THE SOFTWARE.
 */

package com.couchbase.roadrunner.workloads;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.couchbase.client.java.Bucket;
import com.google.common.base.Charsets;
import com.google.common.base.Stopwatch;
import com.google.common.io.Files;

public abstract class Workload implements Runnable {

    /** Configure a reusable logger. */
    private final Logger logger = LoggerFactory.getLogger(Workload.class.getName());

    /** Reference to the Couchbase Bucket */
    private final Bucket bucket;

    /** Name of the Workload */
    private final String workloadName;

    /** Counter of total measured ops */
    private long measuredOps;

    /** Counter of total ops */
    private long totalOps;

    /** Ramp time */
    private long ramp;

    /** Total runtime of this workload thread */
    private Stopwatch elapsed;

    /** Measures */
    private Map<String, List<Stopwatch>> measures;

    private final DocumentFactory documentFactory;

    public Workload(final Bucket bucket, final String name, final int ramp, final DocumentFactory documentFactory) {
        this.bucket = bucket;
        this.workloadName = name;
        this.measures = new HashMap<String, List<Stopwatch>>();
        this.measuredOps = 0;
        this.totalOps = 0;
        this.ramp = ramp;
        this.elapsed = new Stopwatch();
        this.documentFactory = documentFactory;
    }

    public long getTotalOps() {
        return totalOps;
    }

    public void incrTotalOps() {
        totalOps++;
    }

    public void startTimer() {
        elapsed.start();
    }

    public void endTimer() {
        elapsed.stop();
    }

    /**
     * Store a measure for later retrieval.
     *
     * If the ramp-up time is not yet through, don't measure the
     * operation.
     *
     * @param identifier Identifier of the stopwatch.
     * @param watch The stopwatch.
     */
    public void addMeasure(String identifier, Stopwatch watch) {
        if (elapsed.elapsed(TimeUnit.SECONDS) < ramp) {
            return;
        }

        if (!measures.containsKey(identifier)) {
            measures.put(identifier, new ArrayList<Stopwatch>());
        }
        measures.get(identifier).add(watch);
        measuredOps++;
    }

    public Map<String, List<Stopwatch>> getMeasures() {
        return measures;
    }

    public long getMeasuredOps() {
        return measuredOps;
    }

    public Stopwatch totalElapsed() {
        if (elapsed.isRunning()) {
            throw new IllegalStateException("Stopwatch still running!");
        }
        return elapsed;
    }

    /**
     * @return the bucket
     */
    protected Bucket getBucket() {
        return bucket;
    }

    /**
     * @return the workloadName
     */
    public String getWorkloadName() {
        return workloadName;
    }

    /**
     * @return the logger
     */
    public Logger getLogger() {
        return logger;
    }

    public String randomKey() {
        return UUID.randomUUID().toString();
    }

    protected SampleDocument getDocument() {
        return documentFactory.getDocument();
    }

    static interface SampleDocument {
    }

    /**
     * This document consists entirely of random bytes.
     */
    static class RandomDocument implements Serializable, SampleDocument {

        private static final long serialVersionUID = 974277240501163457L;
        public final byte[] payload;

        public RandomDocument(int payloadSize) {
            byte[] bytes = new byte[payloadSize];
            new Random().nextBytes(bytes);
            this.payload = bytes;
        }
    }

    /**
     * Reads a file from disk and uses the contents as the document to be stored.
     * Each line of the file is trimmed and concatenated down to a single string.
     * This allows a "friendly" json/xml/other document with formatting to be
     * given even though the internal representation would not be formatted.
     *
     * @author bvesco, May 21, 2013
     */
    static class FileReaderDocument implements Serializable, SampleDocument {

        private static final long serialVersionUID = 1612506081910846384L;
        public final byte[] payload;

        public FileReaderDocument(String filename) throws IOException {
            File file = new File(filename);
            List<String> lines = Files.readLines(file, Charsets.UTF_8);
            StringBuilder sb = new StringBuilder();
            for (String line : lines) {
                sb.append(line.trim());
            }
            payload = sb.toString().getBytes();
        }
    }

    public static interface DocumentFactory {
        SampleDocument getDocument();
    }

    /**
     * Generates documents of a fixed size but each document has a random sequence
     * of bytes.
     *
     * @author bvesco, May 21, 2013
     */
    public static class FixedSizeRandomDocumentFactory implements DocumentFactory {

        private final Logger logger = LoggerFactory.getLogger(getClass());
        private final int sizeInBytes;

        public FixedSizeRandomDocumentFactory(int sizeInBytes) {
            this.sizeInBytes = sizeInBytes;
            logger.info("Factory using document size of {} bytes", this.sizeInBytes);
        }

        @Override
        public SampleDocument getDocument() {
            return new RandomDocument(sizeInBytes);
        }
    }

    /**
     * Generates documents with bytes that were read from a file. The same
     * document is returned every time.
     *
     * @author bvesco, May 21, 2013
     */
    public static class SingleFileDocumentFactory implements DocumentFactory {

        private final Logger logger = LoggerFactory.getLogger(getClass());
        private final FileReaderDocument document;

        public SingleFileDocumentFactory(String filename) throws IOException {
            this.document = new FileReaderDocument(filename);
            logger.info("Factory using document size of {} bytes from {}", document.payload.length, filename);
        }

        @Override
        public SampleDocument getDocument() {
            return document;
        }
    }
}