<commit_before>/*
 * Copyright (c) 2012-2013 by <NAME>, Zuse Institute Berlin
 *
 *
 * Licensed under the BSD License, see LICENSE file for details.
 *
 */

package org.xtreemfs.common.benchmark;

import java.io.IOException;
import java.util.*;

import org.xtreemfs.common.libxtreemfs.AdminClient;
import org.xtreemfs.common.libxtreemfs.Volume;
import org.xtreemfs.common.libxtreemfs.exceptions.PosixErrorException;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.pbrpc.generatedinterfaces.RPC.POSIXErrno;
import org.xtreemfs.pbrpc.generatedinterfaces.DIR;
import org.xtreemfs.pbrpc.generatedinterfaces.GlobalTypes;
import org.xtreemfs.pbrpc.generatedinterfaces.MRC;

/**
 * Volume Manager (Singleton).
 * <p/>
 * 
 * Class for managing volumes in the benchmark tools. Allows for the creation and deletion of volumes, manages the
 * assignment of volumes to benchmark threads and does bookkeeping of created files and volumes.
 * <p/>
 * The bookkeeping of created volumes is necessary for the deletion (only) of created volumes and files as well as for
 * the filebased benchmarks.
 * 
 * @author jensvfischer
 */
class VolumeManager {

    private static final String              VOLUME_BASE_NAME = "benchmark";

    private static VolumeManager             volumeManager    = null;
    private Config                           config;
    private AdminClient                      client;
    private int                              currentPosition;
    private LinkedList<Volume>               volumes;
    private LinkedList<Volume>               createdVolumes;
    private HashMap<Volume, HashSet<String>> createdFiles;
    private HashMap<Volume, String[]>        filelistsSequentialBenchmark;
    private HashMap<Volume, String[]>        filelistsRandomBenchmark;

    /* init the VolumeManager with params. This only needs to be called once */
    static void init(Config config) throws Exception {
        if (volumeManager == null) {
            volumeManager = new VolumeManager(config);
        }
    }

    /* returns the (singleton) instance of the VolumeManager */
    static VolumeManager getInstance() throws Exception {
        if (volumeManager == null)
            throw new RuntimeException("Volume Manager not initialized");
        return volumeManager;
    }

    /* private constructor, used by init */
    private VolumeManager(Config config) throws Exception {
        this.config = config;
        currentPosition = 0;
        this.client = ClientManager.getInstance().getNewClient(config);
        this.volumes = new LinkedList<Volume>();
        this.createdVolumes = new LinkedList<Volume>();
        this.filelistsSequentialBenchmark = new HashMap<Volume, String[]>(5);
        this.filelistsRandomBenchmark = new HashMap<Volume, String[]>(5);
        this.createdFiles = new HashMap<Volume, HashSet<String>>();
    }

    /* cycles through the list of volumes to assign to volumes to benchmarks */
    Volume getNextVolume() {
        return volumes.get(currentPosition++);
    }

    /*
     * reset the position counter of the volume list. Needs to be called if one wants to reuse the volumes for a
     * consecutive benchmark
     */
    void reset() {
        currentPosition = 0;
    }

    /* used if no volumes were specified */
    void createDefaultVolumes(int numberOfVolumes) throws IOException {
        for (int i = 0; i < numberOfVolumes; i++) {
            Volume volume = createAndOpenVolume(VOLUME_BASE_NAME + i);
            addToVolumes(volume);
        }
    }

    /* add a volume to the volume list */
    private void addToVolumes(Volume volume) {
        if (!volumes.contains(volume))
            volumes.add(volume);
    }

    /* opens multiple volumes (and creates and opens volumes if they do not exist) */
    void openVolumes(String... volumeName) throws IOException {
        this.volumes = new LinkedList<Volume>();
        for (String each : volumeName) {
            volumes.add(createAndOpenVolume(each));
        }
    }

    /* opens a single volume (or creates and opens a volume if it does not exist) */
    private Volume createAndOpenVolume(String volumeName) throws IOException {
        Volume volume = null;
        try {
            List<GlobalTypes.KeyValuePair> volumeAttributes = new ArrayList<GlobalTypes.KeyValuePair>();
            client.createVolume(config.getAuth(), config.getUserCredentials(), volumeName, 511, config.getUserName(), config.getGroup(),
                    GlobalTypes.AccessControlPolicyType.ACCESS_CONTROL_POLICY_POSIX,
                    GlobalTypes.StripingPolicyType.STRIPING_POLICY_RAID0, config.getStripeSizeInKiB(),
                    config.getStripeWidth(), volumeAttributes);
            volume = client.openVolume(volumeName, config.getSslOptions(), config.getOptions());
            createdVolumes.add(volume);
            createDirStructure(volume);
            Logging.logMessage(Logging.LEVEL_INFO, Logging.Category.tool, this, "Created volume %s", volumeName);
        } catch (PosixErrorException e) {
            if (e.getPosixError() == POSIXErrno.POSIX_ERROR_EEXIST) {
                volume = client.openVolume(volumeName, config.getSslOptions(), config.getOptions());
            } else
                throw e;
        }
        volume.setOSDSelectionPolicy(config.getUserCredentials(), config.getOsdSelectionPolicies());
        Map<String, String> attributes = config.getPolicyAttributes();
        for (String attribute : attributes.keySet())
            volume.setPolicyAttribute(config.getUserCredentials(), attribute, attributes.get(attribute));
        return volume;
    }

    private void createDirStructure(Volume volume) throws IOException {
        volume.createDirectory(config.getUserCredentials(), "/benchmarks/sequentialBenchmark", 0777, true);
        volume.createDirectory(config.getUserCredentials(), "/benchmarks/randomBenchmark", 0777, true);
    }

    /*
     * adds a filelist with files from a sequential benchmark (used to pass the list of files written by a sequential
     * write benchmark to a sequential read benchmark)
     */<commit_msg>jens-benchmark/server: Fix dir structure creation in VolumeManager<commit_after>/*
 * Copyright (c) 2012-2013 by <NAME>, Zuse Institute Berlin
 *
 *
 * Licensed under the BSD License, see LICENSE file for details.
 *
 */

package org.xtreemfs.common.benchmark;

import java.io.IOException;
import java.util.*;

import org.xtreemfs.common.libxtreemfs.AdminClient;
import org.xtreemfs.common.libxtreemfs.Volume;
import org.xtreemfs.common.libxtreemfs.exceptions.PosixErrorException;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.pbrpc.generatedinterfaces.RPC.POSIXErrno;
import org.xtreemfs.pbrpc.generatedinterfaces.DIR;
import org.xtreemfs.pbrpc.generatedinterfaces.GlobalTypes;
import org.xtreemfs.pbrpc.generatedinterfaces.MRC;

/**
 * Volume Manager (Singleton).
 * <p/>
 * 
 * Class for managing volumes in the benchmark tools. Allows for the creation and deletion of volumes, manages the
 * assignment of volumes to benchmark threads and does bookkeeping of created files and volumes.
 * <p/>
 * The bookkeeping of created volumes is necessary for the deletion (only) of created volumes and files as well as for
 * the filebased benchmarks.
 * 
 * @author jensvfischer
 */
class VolumeManager {

    private static final String              VOLUME_BASE_NAME = "benchmark";

    private static VolumeManager             volumeManager    = null;
    private Config                           config;
    private AdminClient                      client;
    private int                              currentPosition;
    private LinkedList<Volume>               volumes;
    private LinkedList<Volume>               createdVolumes;
    private HashMap<Volume, HashSet<String>> createdFiles;
    private HashMap<Volume, String[]>        filelistsSequentialBenchmark;
    private HashMap<Volume, String[]>        filelistsRandomBenchmark;

    /* init the VolumeManager with params. This only needs to be called once */
    static void init(Config config) throws Exception {
        if (volumeManager == null) {
            volumeManager = new VolumeManager(config);
        }
    }

    /* returns the (singleton) instance of the VolumeManager */
    static VolumeManager getInstance() throws Exception {
        if (volumeManager == null)
            throw new RuntimeException("Volume Manager not initialized");
        return volumeManager;
    }

    /* private constructor, used by init */
    private VolumeManager(Config config) throws Exception {
        this.config = config;
        currentPosition = 0;
        this.client = ClientManager.getInstance().getNewClient(config);
        this.volumes = new LinkedList<Volume>();
        this.createdVolumes = new LinkedList<Volume>();
        this.filelistsSequentialBenchmark = new HashMap<Volume, String[]>(5);
        this.filelistsRandomBenchmark = new HashMap<Volume, String[]>(5);
        this.createdFiles = new HashMap<Volume, HashSet<String>>();
    }

    /* cycles through the list of volumes to assign to volumes to benchmarks */
    Volume getNextVolume() {
        return volumes.get(currentPosition++);
    }

    /*
     * reset the position counter of the volume list. Needs to be called if one wants to reuse the volumes for a
     * consecutive benchmark
     */
    void reset() {
        currentPosition = 0;
    }

    /* used if no volumes were specified */
    void createDefaultVolumes(int numberOfVolumes) throws IOException {
        for (int i = 0; i < numberOfVolumes; i++) {
            Volume volume = createAndOpenVolume(VOLUME_BASE_NAME + i);
            addToVolumes(volume);
        }
    }

    /* add a volume to the volume list */
    private void addToVolumes(Volume volume) {
        if (!volumes.contains(volume))
            volumes.add(volume);
    }

    /* opens multiple volumes (and creates and opens volumes if they do not exist) */
    void openVolumes(String... volumeName) throws IOException {
        this.volumes = new LinkedList<Volume>();
        for (String each : volumeName) {
            volumes.add(createAndOpenVolume(each));
        }
    }

    /* opens a single volume (or creates and opens a volume if it does not exist) */
    private Volume createAndOpenVolume(String volumeName) throws IOException {
        Volume volume = null;
        try { /* try creating the volume */
            List<GlobalTypes.KeyValuePair> volumeAttributes = new ArrayList<GlobalTypes.KeyValuePair>();
            client.createVolume(config.getAuth(), config.getUserCredentials(), volumeName, 511, config.getUserName(),
                    config.getGroup(), GlobalTypes.AccessControlPolicyType.ACCESS_CONTROL_POLICY_POSIX,
                    GlobalTypes.StripingPolicyType.STRIPING_POLICY_RAID0, config.getStripeSizeInKiB(),
                    config.getStripeWidth(), volumeAttributes);
            volume = client.openVolume(volumeName, config.getSslOptions(), config.getOptions());
            createdVolumes.add(volume);
            Logging.logMessage(Logging.LEVEL_INFO, Logging.Category.tool, this, "Created volume %s", volumeName);
        } catch (PosixErrorException e) {
            if (e.getPosixError() == POSIXErrno.POSIX_ERROR_EEXIST) { /* i.e. volume already exists */
                volume = client.openVolume(volumeName, config.getSslOptions(), config.getOptions());
            } else
                throw e;
        }
        createDirStructure(volume);
        volume.setOSDSelectionPolicy(config.getUserCredentials(), config.getOsdSelectionPolicies());
        Map<String, String> attributes = config.getPolicyAttributes();
        for (String attribute : attributes.keySet())
            volume.setPolicyAttribute(config.getUserCredentials(), attribute, attributes.get(attribute));
        return volume;
    }

    private void createDirStructure(Volume volume) throws IOException {
        createDir(volume, "/benchmarks/sequentialBenchmark");
        createDir(volume, "/benchmarks/randomBenchmark");
    }

    private void createDir(Volume volume, String directory) throws IOException {

        try { /* try to create directory benchmark */
            volume.createDirectory(config.getUserCredentials(), directory, 0777, true);
            Logging.logMessage(Logging.LEVEL_INFO, Logging.Category.tool, this,
                    "/benchmarks/randomBenchmark created on volume %s", volume.getVolumeName());

        /* catch should be entered when directory already exists */
        } catch (PosixErrorException e) {

            /* if its not because directory already exists, throw error again */
            if (!(e.getPosixError() == POSIXErrno.POSIX_ERROR_EEXIST)) {
                throw e;
            }
        }

    }

    /*
     * adds a filelist with files from a sequential benchmark (used to pass the list of files written by a sequential
     * write benchmark to a sequential read benchmark)
     */
{'fraction_non_alphanumeric': 0.08924731182795699, 'fraction_numerical': 0.003533026113671275, 'mean_word_length': 2.846676514032496, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6271994', 'n_tokens_mistral': 3442, 'n_tokens_neox': 3324, 'n_words': 967}