Imported Upstream version 1.5.1

This commit is contained in:
Mario Fetka
2020-09-22 02:25:22 +02:00
commit 434d6067d9
2103 changed files with 928962 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="Flease" default="default" basedir=".">
<description>Builds, tests, and runs the project Flease.</description>
<import file="nbproject/build-impl-1.6.5.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="Flease-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

75
java/flease/build.xml Normal file
View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="Flease" default="default" basedir=".">
<description>Builds, tests, and runs the project Flease.</description>
<import file="nbproject/build-impl.xml"/>
<import file="nbproject/profiler-build-impl.xml"/> <!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="Flease-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry combineaccessrules="false" kind="src" path="/xtreemfs_foundation"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="../lib/test/junit-4.11.jar"/>
<classpathentry kind="lib" path="../lib/test/hamcrest-core-1.3.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>xtreemfs_flease</name>
<comment></comment>
<projects>
<project>xtreemfs_foundation</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

3
java/flease/manifest.mf Normal file
View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

View File

@@ -0,0 +1,892 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
For the purpose of easier reading the script
is divided into following sections:
- initialization
- compilation
- jar
- execution
- debugging
- javadoc
- junit compilation
- junit execution
- junit debugging
- applet
- cleanup
-->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Flease-impl">
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
<!--
======================
INITIALIZATION SECTION
======================
-->
<target name="-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init" name="-init-private">
<property file="nbproject/private/config.properties"/>
<property file="nbproject/private/configs/${config}.properties"/>
<property file="nbproject/private/private.properties"/>
</target>
<target depends="-pre-init,-init-private" name="-init-user">
<property file="${user.properties.file}"/>
<!-- The two properties below are usually overridden -->
<!-- by the active platform. Just a fallback. -->
<property name="default.javac.source" value="1.4"/>
<property name="default.javac.target" value="1.4"/>
</target>
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
<property file="nbproject/configs/${config}.properties"/>
<property file="nbproject/project.properties"/>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
<available file="${manifest.file}" property="manifest.available"/>
<available file="${application.splash}" property="splashscreen.available"/>
<condition property="main.class.available">
<and>
<isset property="main.class"/>
<not>
<equals arg1="${main.class}" arg2="" trim="true"/>
</not>
</and>
</condition>
<condition property="manifest.available+main.class">
<and>
<isset property="manifest.available"/>
<isset property="main.class.available"/>
</and>
</condition>
<condition property="do.mkdist">
<and>
<isset property="libs.CopyLibs.classpath"/>
<not>
<istrue value="${mkdist.disabled}"/>
</not>
</and>
</condition>
<condition property="manifest.available+main.class+mkdist.available">
<and>
<istrue value="${manifest.available+main.class}"/>
<isset property="do.mkdist"/>
</and>
</condition>
<condition property="manifest.available+main.class+mkdist.available+splashscreen.available">
<and>
<istrue value="${manifest.available+main.class+mkdist.available}"/>
<istrue value="${splashscreen.available}"/>
</and>
</condition>
<condition property="do.archive">
<not>
<istrue value="${jar.archive.disabled}"/>
</not>
</condition>
<condition property="do.archive+manifest.available">
<and>
<isset property="manifest.available"/>
<istrue value="${do.archive}"/>
</and>
</condition>
<condition property="do.archive+manifest.available+main.class">
<and>
<istrue value="${manifest.available+main.class}"/>
<istrue value="${do.archive}"/>
</and>
</condition>
<condition property="do.archive+manifest.available+main.class+mkdist.available">
<and>
<istrue value="${manifest.available+main.class+mkdist.available}"/>
<istrue value="${do.archive}"/>
</and>
</condition>
<condition property="do.archive+manifest.available+main.class+mkdist.available+splashscreen.available">
<and>
<istrue value="${manifest.available+main.class+mkdist.available+splashscreen.available}"/>
<istrue value="${do.archive}"/>
</and>
</condition>
<condition property="have.tests">
<or>
<available file="${test.src.dir}"/>
</or>
</condition>
<condition property="have.sources">
<or>
<available file="${src.dir}"/>
</or>
</condition>
<condition property="netbeans.home+have.tests">
<and>
<isset property="netbeans.home"/>
<isset property="have.tests"/>
</and>
</condition>
<condition property="no.javadoc.preview">
<and>
<isset property="javadoc.preview"/>
<isfalse value="${javadoc.preview}"/>
</and>
</condition>
<property name="run.jvmargs" value=""/>
<property name="javac.compilerargs" value=""/>
<property name="work.dir" value="${basedir}"/>
<condition property="no.deps">
<and>
<istrue value="${no.dependencies}"/>
</and>
</condition>
<property name="javac.debug" value="true"/>
<property name="javadoc.preview" value="true"/>
<property name="application.args" value=""/>
<property name="source.encoding" value="${file.encoding}"/>
<property name="runtime.encoding" value="${source.encoding}"/>
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
<and>
<isset property="javadoc.encoding"/>
<not>
<equals arg1="${javadoc.encoding}" arg2=""/>
</not>
</and>
</condition>
<property name="javadoc.encoding.used" value="${source.encoding}"/>
<property name="includes" value="**"/>
<property name="excludes" value=""/>
<property name="do.depend" value="false"/>
<condition property="do.depend.true">
<istrue value="${do.depend}"/>
</condition>
<path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
<condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
<length length="0" string="${endorsed.classpath}" when="greater"/>
</condition>
<property name="javac.fork" value="false"/>
<property name="jar.index" value="false"/>
<available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
<fail unless="src.dir">Must set src.dir</fail>
<fail unless="test.src.dir">Must set test.src.dir</fail>
<fail unless="build.dir">Must set build.dir</fail>
<fail unless="dist.dir">Must set dist.dir</fail>
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
<fail unless="dist.jar">Must set dist.jar</fail>
</target>
<target name="-init-macrodef-property">
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
</target>
<target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<attribute default="${javac.processorpath}" name="processorpath"/>
<attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="${javac.debug}" name="debug"/>
<attribute default="${empty.dir}" name="sourcepath"/>
<attribute default="${empty.dir}" name="gensrcdir"/>
<element name="customize" optional="true"/>
<sequential>
<property location="${build.dir}/empty" name="empty.dir"/>
<mkdir dir="${empty.dir}"/>
<mkdir dir="@{gensrcdir}"/>
<mkdir dir="@{apgeneratedsrcdir}"/>
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
<src>
<dirset dir="@{gensrcdir}">
<include name="*"/>
</dirset>
</src>
<classpath>
<path path="@{classpath}"/>
</classpath>
<compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
<compilerarg line="${javac.compilerargs}"/>
<compilerarg value="-processorpath"/>
<compilerarg path="@{processorpath}:${empty.dir}"/>
<compilerarg line="${ap.processors.internal}"/>
<compilerarg line="${annotation.processing.processor.options}"/>
<compilerarg value="-s"/>
<compilerarg path="@{apgeneratedsrcdir}"/>
<compilerarg line="${ap.proc.none.internal}"/>
<customize/>
</javac>
</sequential>
</macrodef>
</target>
<target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<attribute default="${javac.processorpath}" name="processorpath"/>
<attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="${javac.debug}" name="debug"/>
<attribute default="${empty.dir}" name="sourcepath"/>
<attribute default="${empty.dir}" name="gensrcdir"/>
<element name="customize" optional="true"/>
<sequential>
<property location="${build.dir}/empty" name="empty.dir"/>
<mkdir dir="${empty.dir}"/>
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
<src>
<dirset dir="@{gensrcdir}" erroronmissingdir="false">
<include name="*"/>
</dirset>
</src>
<classpath>
<path path="@{classpath}"/>
</classpath>
<compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
<compilerarg line="${javac.compilerargs}"/>
<customize/>
</javac>
</sequential>
</macrodef>
</target>
<target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<sequential>
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</depend>
</sequential>
</macrodef>
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${build.classes.dir}" name="destdir"/>
<sequential>
<fail unless="javac.includes">Must set javac.includes</fail>
<pathconvert pathsep="${line.separator}" property="javac.includes.binary">
<path>
<filelist dir="@{destdir}" files="${javac.includes}"/>
</path>
<globmapper from="*.java" to="*.class"/>
</pathconvert>
<tempfile deleteonexit="true" property="javac.includesfile.binary"/>
<echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
<delete>
<files includesfile="${javac.includesfile.binary}"/>
</delete>
<delete file="${javac.includesfile.binary}"/>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-junit">
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="**" name="testincludes"/>
<sequential>
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true" tempdir="${build.dir}">
<batchtest todir="${build.test.results.dir}">
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
</batchtest>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg line="${run.jvmargs}"/>
</junit>
</sequential>
</macrodef>
</target>
<target depends="-init-debug-args" name="-init-macrodef-nbjpda">
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="name"/>
<attribute default="${debug.classpath}" name="classpath"/>
<attribute default="" name="stopclassname"/>
<sequential>
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</nbjpdastart>
</sequential>
</macrodef>
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${build.classes.dir}" name="dir"/>
<sequential>
<nbjpdareload>
<fileset dir="@{dir}" includes="${fix.classes}">
<include name="${fix.includes}*.class"/>
</fileset>
</nbjpdareload>
</sequential>
</macrodef>
</target>
<target name="-init-debug-args">
<property name="version-output" value="java version &quot;${ant.java.version}"/>
<condition property="have-jdk-older-than-1.4">
<or>
<contains string="${version-output}" substring="java version &quot;1.0"/>
<contains string="${version-output}" substring="java version &quot;1.1"/>
<contains string="${version-output}" substring="java version &quot;1.2"/>
<contains string="${version-output}" substring="java version &quot;1.3"/>
</or>
</condition>
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
<istrue value="${have-jdk-older-than-1.4}"/>
</condition>
<condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
<os family="windows"/>
</condition>
<condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
<isset property="debug.transport"/>
</condition>
</target>
<target depends="-init-debug-args" name="-init-macrodef-debug">
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${main.class}" name="classname"/>
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
<jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
<redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="@{classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-java">
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="classname"/>
<attribute default="${run.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
<redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="@{classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-copylibs">
<macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
<element name="customize" optional="true"/>
<sequential>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Class-Path" value="${jar.classpath}"/>
<customize/>
</manifest>
</copylibs>
</sequential>
</macrodef>
</target>
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}"/>
</jar>
</presetdef>
</target>
<target name="-init-ap-cmdline-properties">
<property name="annotation.processing.enabled" value="true"/>
<property name="annotation.processing.processors.list" value=""/>
<property name="annotation.processing.processor.options" value=""/>
<property name="annotation.processing.run.all.processors" value="true"/>
<property name="javac.processorpath" value="${javac.classpath}"/>
<property name="javac.test.processorpath" value="${javac.test.classpath}"/>
<condition property="ap.supported.internal" value="true">
<!-- 'matches' below does not work with ant 1.6.5. Therefore disabled in this file and set to always true. -->
<istrue value="true"/>
<!--
<not>
<matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
</not>
-->
</condition>
</target>
<target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
<condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
<isfalse value="${annotation.processing.run.all.processors}"/>
</condition>
<condition else="" property="ap.proc.none.internal" value="-proc:none">
<isfalse value="${annotation.processing.enabled}"/>
</condition>
</target>
<target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
<property name="ap.cmd.line.internal" value=""/>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
<!--
===================
COMPILATION SECTION
===================
-->
<target name="-deps-jar-init" unless="built-jar.properties">
<property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
<delete file="${built-jar.properties}" quiet="true"/>
</target>
<target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
<echo level="warn" message="Cycle detected: Flease was already built"/>
</target>
<target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
<mkdir dir="${build.dir}"/>
<touch file="${built-jar.properties}" verbose="false"/>
<property file="${built-jar.properties}" prefix="already.built.jar."/>
<antcall target="-warn-already-built-jar"/>
<propertyfile file="${built-jar.properties}">
<entry key="${basedir}" value=""/>
</propertyfile>
</target>
<target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
<target depends="init" name="-check-automatic-build">
<available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
</target>
<target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
<antcall target="clean"/>
</target>
<target depends="init,deps-jar" name="-pre-pre-compile">
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="-pre-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-depend">
<pathconvert property="build.generated.subdirs">
<dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
<include name="*"/>
</dirset>
</pathconvert>
<j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
<j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target if="has.persistence.xml" name="-copy-persistence-xml">
<mkdir dir="${build.classes.dir}/META-INF"/>
<copy todir="${build.classes.dir}/META-INF">
<fileset dir="${meta.inf.dir}" includes="persistence.xml"/>
</copy>
</target>
<target name="-post-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
<target name="-pre-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile/>
<j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
</target>
<target name="-post-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
<!--
====================
JAR BUILDING SECTION
====================
-->
<target depends="init" name="-pre-pre-jar">
<dirname file="${dist.jar}" property="dist.jar.dir"/>
<mkdir dir="${dist.jar.dir}"/>
</target>
<target name="-pre-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available">
<j2seproject1:jar/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
<j2seproject1:jar manifest="${manifest.file}"/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
<j2seproject1:jar manifest="${manifest.file}">
<j2seproject1:manifest>
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
</j2seproject1:manifest>
</j2seproject1:jar>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<pathconvert property="run.classpath.with.dist.jar">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
</pathconvert>
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar,-init-macrodef-copylibs" if="do.archive+manifest.available+main.class+mkdist.available+splashscreen.available" name="-do-jar-with-libraries-and-splashscreen">
<basename file="${application.splash}" property="splashscreen.basename"/>
<mkdir dir="${build.classes.dir}/META-INF"/>
<copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
<j2seproject3:copylibs>
<customize>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
</customize>
</j2seproject3:copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar,-init-macrodef-copylibs" if="do.archive+manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries" unless="splashscreen.available">
<j2seproject3:copylibs>
<customize>
<attribute name="Main-Class" value="${main.class}"/>
</customize>
</j2seproject3:copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target name="-post-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries-and-splashscreen,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
<!--
=================
EXECUTION SECTION
=================
-->
<target depends="init,compile" description="Run a main class." name="run">
<j2seproject1:java>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject1:java>
</target>
<target name="-do-not-recompile">
<property name="javac.includes.binary" value=""/>
</target>
<target depends="init,compile-single" name="run-single">
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
<j2seproject1:java classname="${run.class}"/>
</target>
<target depends="init,compile-test-single" name="run-test-with-main">
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
<j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
</target>
<!--
=================
DEBUGGING SECTION
=================
-->
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
<j2seproject1:nbjpdastart name="${debug.class}"/>
</target>
<target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
</target>
<target depends="init,compile" name="-debug-start-debuggee">
<j2seproject3:debug>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
</target>
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
<j2seproject3:debug classname="${debug.class}"/>
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
<target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
<j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
</target>
<target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
<target depends="init" name="-pre-debug-fix">
<fail unless="fix.includes">Must set fix.includes</fail>
<property name="javac.includes" value="${fix.includes}.java"/>
</target>
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
<j2seproject1:nbjpdareload/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
<!--
===============
JAVADOC SECTION
===============
-->
<target depends="init" if="have.sources" name="-javadoc-build">
<mkdir dir="${dist.javadoc.dir}"/>
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
<classpath>
<path path="${javac.classpath}"/>
</classpath>
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
<filename name="**/*.java"/>
</fileset>
<fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
<include name="**/*.java"/>
</fileset>
</javadoc>
<copy todir="${dist.javadoc.dir}">
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
<filename name="**/doc-files/**"/>
</fileset>
<fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
<include name="**/doc-files/**"/>
</fileset>
</copy>
</target>
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
</target>
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
<!--
=========================
JUNIT COMPILATION SECTION
=========================
-->
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
<mkdir dir="${build.test.classes.dir}"/>
</target>
<target name="-pre-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-test-depend">
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
<j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
<target name="-pre-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
<j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
<!--
=======================
JUNIT EXECUTION SECTION
=======================
-->
<target depends="init" if="have.tests" name="-pre-test-run">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
<j2seproject3:junit testincludes="**/*Test.java"/>
</target>
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
<fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
</target>
<target depends="init" if="have.tests" name="test-report"/>
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
<target depends="init" if="have.tests" name="-pre-test-run-single">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
<j2seproject3:junit excludes="" includes="${test.includes}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
<fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
<!--
=======================
JUNIT DEBUGGING SECTION
=======================
-->
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
<delete file="${test.report.file}"/>
<mkdir dir="${build.test.results.dir}"/>
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
<customize>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<arg value="${test.class}"/>
<arg value="showoutput=true"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
</target>
<target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
<!--
=========================
APPLET EXECUTION SECTION
=========================
-->
<target depends="init,compile-single" name="run-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject1:java classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject1:java>
</target>
<!--
=========================
APPLET DEBUGGING SECTION
=========================
-->
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject3:debug classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
<!--
===============
CLEANUP SECTION
===============
-->
<target name="-deps-clean-init" unless="built-clean.properties">
<property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
<delete file="${built-clean.properties}" quiet="true"/>
</target>
<target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
<echo level="warn" message="Cycle detected: Flease was already built"/>
</target>
<target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
<mkdir dir="${build.dir}"/>
<touch file="${built-clean.properties}" verbose="false"/>
<property file="${built-clean.properties}" prefix="already.built.clean."/>
<antcall target="-warn-already-built-clean"/>
<propertyfile file="${built-clean.properties}">
<entry key="${basedir}" value=""/>
</propertyfile>
</target>
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
</target>
<target name="-post-clean">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
<target name="-check-call-dep">
<property file="${call.built.properties}" prefix="already.built."/>
<condition property="should.call.dep">
<not>
<isset property="already.built.${call.subproject}"/>
</not>
</condition>
</target>
<target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
<ant antfile="${call.script}" inheritall="false" target="${call.target}">
<propertyset>
<propertyref prefix="transfer."/>
<mapper from="transfer.*" to="*" type="glob"/>
</propertyset>
</ant>
</target>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
build.xml.data.CRC32=3d699ec7
build.xml.script.CRC32=d8a5a904
build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=d06e30bd
nbproject/build-impl.xml.script.CRC32=318c6c3f
nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45
nbproject/profiler-build-impl.xml.data.CRC32=3d699ec7
nbproject/profiler-build-impl.xml.script.CRC32=abda56ed
nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf@1.6.1

View File

@@ -0,0 +1,6 @@
compile.on.save=true
do.depend=false
do.jar=true
javac.debug=true
javadoc.preview=true
user.properties.file=/home/kleineweber/.netbeans/7.0/build.properties

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<data xmlns="http://www.netbeans.org/ns/profiler/1" version="0.9.1"/>
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
</project-private>

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="2_profiler.settings.code.region.cpu.res.buf.size">1000</entry>
<entry key="2_profiler.settings.sort.results.by.thread.cpu.time">false</entry>
<entry key="0_profiler.settings.instrumentation.filter.selectedprofiler.filter.type">profiler.simple.filter</entry>
<entry key="0_profiler.settings.instrument.empty.methods">false</entry>
<entry key="3_profiler.settings.override.jvm.args"/>
<entry key="0_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.name"/>
<entry key="1_profiler.settings.profiling.type">8</entry>
<entry key="0_profiler.settings.cpu.exclude.wait.time">true</entry>
<entry key="0_profiler.settings.override.working.dir"/>
<entry key="3_profiler.settings.instrument.empty.methods">false</entry>
<entry key="1_profiler.settings.thread.cpu.timer.on">false</entry>
<entry key="1_profiler.settings.instrumentation.root.methods.size">0</entry>
<entry key="3_profiler.settings.obj.alloc.stack.sampling.depth">0</entry>
<entry key="2_profiler.settings.override">false</entry>
<entry key="profiler.settings.lastselected">2</entry>
<entry key="2_profiler.settings.instrument.spawned.threads">true</entry>
<entry key="0_profiler.settings.threads.monitoring.enabled">false</entry>
<entry key="0_profiler.settings.istrument.getter.setter.methods">false</entry>
<entry key="3_profiler.settings.cpu.quick.filterprofiler.simple.filter.value"/>
<entry key="2_profiler.settings.instrumentation.filter.selectedprofiler.filter.type">profiler.simple.filter</entry>
<entry key="3_profiler.settings.cpu.quick.filterprofiler.simple.filter.type">1</entry>
<entry key="2_profiler.settings.n.profiled.threads.limit">32</entry>
<entry key="3_profiler.settings.instr.scheme">1</entry>
<entry key="1_profiler.settings.sort.results.by.thread.cpu.time">false</entry>
<entry key="2_profiler.settings.instr.scheme">3</entry>
<entry key="1_profiler.settings.instrument.method.invoke">true</entry>
<entry key="3_profiler.settings.profilingpoints.enabled">true</entry>
<entry key="1_profiler.settings.instr.scheme">3</entry>
<entry key="2_profiler.settings.sampling.interval">10</entry>
<entry key="0_profiler.settings.instr.scheme">1</entry>
<entry key="1_profiler.settings.run.gc.on.get.results.in.memory.profiling">true</entry>
<entry key="2_profiler.settings.settings.name">New CPU Analysis</entry>
<entry key="0_profiler.settings.sort.results.by.thread.cpu.time">false</entry>
<entry key="0_profiler.settings.profiling.type">1</entry>
<entry key="1_profiler.settings.cpu.exclude.wait.time">true</entry>
<entry key="3_profiler.settings.cpu.quick.filterprofiler.simple.filter.name">Quick filter...</entry>
<entry key="2_profiler.settings.obj.alloc.stack.sampling.interval">10</entry>
<entry key="3_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.type">0</entry>
<entry key="3_profiler.settings.override">false</entry>
<entry key="1_profiler.settings.obj.alloc.stack.sampling.depth">0</entry>
<entry key="1_profiler.settings.cpu.quick.filterprofiler.filter.type">profiler.simple.filter</entry>
<entry key="1_profiler.settings.instrumentation.marker.methods.size">0</entry>
<entry key="2_profiler.settings.thread.cpu.timer.on">false</entry>
<entry key="0_profiler.settigns.ispreset">true</entry>
<entry key="0_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.value"/>
<entry key="3_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.name"/>
<entry key="2_profiler.settings.override.working.dir"/>
<entry key="0_profiler.settings.cpu.quick.filterprofiler.simple.filter.type">1</entry>
<entry key="2_profiler.settings.cpu.quick.filterprofiler.simple.filter.value"/>
<entry key="2_profiler.settings.override.jvm.args"/>
<entry key="0_profiler.settings.profile.underlying.framework">false</entry>
<entry key="2_profiler.settings.profile.underlying.framework">false</entry>
<entry key="3_profiler.settings.thread.cpu.timer.on">false</entry>
<entry key="2_profiler.settings.cpu.exclude.wait.time">true</entry>
<entry key="2_profiler.settings.threads.monitoring.enabled">false</entry>
<entry key="1_profiler.settings.instrument.spawned.threads">false</entry>
<entry key="1_profiler.settings.n.profiled.threads.limit">32</entry>
<entry key="0_profiler.settings.cpu.quick.filterprofiler.simple.filter.name">Quick filter...</entry>
<entry key="2_profiler.settings.instrumentation.root.methods.size">0</entry>
<entry key="2_profiler.settings.instrument.empty.methods">false</entry>
<entry key="2_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.type">0</entry>
<entry key="3_profiler.settings.cpu.profiling.type">0</entry>
<entry key="1_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.value"/>
<entry key="3_profiler.settings.cpu.quick.filterprofiler.filter.type">profiler.simple.filter</entry>
<entry key="1_profiler.settings.sampling.interval">10</entry>
<entry key="2_profiler.settings.cpu.profiling.type">0</entry>
<entry key="0_profiler.settings.run.gc.on.get.results.in.memory.profiling">true</entry>
<entry key="1_profiler.settigns.ispreset">true</entry>
<entry key="2_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.name">Profile all classes</entry>
<entry key="0_profiler.settings.instrument.method.invoke">true</entry>
<entry key="0_profiler.settings.obj.alloc.stack.sampling.interval">10</entry>
<entry key="3_profiler.settings.cpu.exclude.wait.time">true</entry>
<entry key="1_profiler.settings.cpu.quick.filterprofiler.simple.filter.value"/>
<entry key="1_profiler.settings.code.region.cpu.res.buf.size">1000</entry>
<entry key="3_profiler.settings.instrumentation.marker.methods.size">0</entry>
<entry key="3_profiler.settings.instrument.method.invoke">true</entry>
<entry key="3_profiler.settings.code.region.cpu.res.buf.size">1000</entry>
<entry key="0_profiler.settings.instrumentation.marker.methods.size">0</entry>
<entry key="1_profiler.settings.instrumentation.filter.selectedprofiler.filter.type">profiler.simple.filter</entry>
<entry key="0_profiler.settings.override">false</entry>
<entry key="3_profiler.settings.obj.alloc.stack.sampling.interval">10</entry>
<entry key="1_profiler.settings.settings.name">Analyze Performance</entry>
<entry key="2_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.value"/>
<entry key="1_profiler.settings.cpu.quick.filterprofiler.simple.filter.type">1</entry>
<entry key="1_profiler.settings.cpu.profiling.type">0</entry>
<entry key="1_profiler.settings.override.jvm.args"/>
<entry key="2_profiler.settings.obj.alloc.stack.sampling.depth">0</entry>
<entry key="1_profiler.settings.instrument.empty.methods">false</entry>
<entry key="0_profiler.settings.cpu.quick.filterprofiler.filter.type">profiler.simple.filter</entry>
<entry key="3_profiler.settings.run.gc.on.get.results.in.memory.profiling">true</entry>
<entry key="1_profiler.settings.cpu.quick.filterprofiler.simple.filter.name">Quick filter...</entry>
<entry key="3_profiler.settings.instrument.spawned.threads">false</entry>
<entry key="2_profiler.settigns.ispreset">false</entry>
<entry key="1_profiler.settings.threads.monitoring.enabled">false</entry>
<entry key="0_profiler.settings.instrumentation.root.methods.size">0</entry>
<entry key="3_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.value"/>
<entry key="1_profiler.settings.override.working.dir"/>
<entry key="3_profiler.settings.istrument.getter.setter.methods">false</entry>
<entry key="1_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.type">0</entry>
<entry key="0_profiler.settings.n.profiled.threads.limit">32</entry>
<entry key="0_profiler.settings.cpu.quick.filterprofiler.simple.filter.value"/>
<entry key="3_profiler.settings.instrumentation.root.methods.size">0</entry>
<entry key="3_profiler.settings.n.profiled.threads.limit">32</entry>
<entry key="0_profiler.settings.cpu.profiling.type">0</entry>
<entry key="3_profiler.settings.instrumentation.filter.selectedprofiler.filter.type">profiler.simple.filter</entry>
<entry key="3_profiler.settings.settings.name">Analyze Memory</entry>
<entry key="3_profiler.settings.profiling.type">2</entry>
<entry key="0_profiler.settings.instrument.spawned.threads">false</entry>
<entry key="1_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.name">Profile all classes</entry>
<entry key="2_profiler.settings.instrumentation.marker.methods.size">0</entry>
<entry key="0_profiler.settings.obj.alloc.stack.sampling.depth">0</entry>
<entry key="3_profiler.settings.sampling.interval">10</entry>
<entry key="2_profiler.settings.cpu.quick.filterprofiler.filter.type">profiler.simple.filter</entry>
<entry key="0_profiler.settings.profilingpoints.enabled">true</entry>
<entry key="2_profiler.settings.cpu.quick.filterprofiler.simple.filter.type">1</entry>
<entry key="3_profiler.settigns.ispreset">true</entry>
<entry key="1_profiler.settings.override">false</entry>
<entry key="1_profiler.settings.obj.alloc.stack.sampling.interval">10</entry>
<entry key="3_profiler.settings.override.working.dir"/>
<entry key="2_profiler.settings.istrument.getter.setter.methods">false</entry>
<entry key="0_profiler.settings.sampling.interval">10</entry>
<entry key="1_profiler.settings.profile.underlying.framework">false</entry>
<entry key="2_profiler.settings.instrument.method.invoke">true</entry>
<entry key="3_profiler.settings.profile.underlying.framework">false</entry>
<entry key="1_profiler.settings.profilingpoints.enabled">true</entry>
<entry key="1_profiler.settings.istrument.getter.setter.methods">false</entry>
<entry key="2_profiler.settings.cpu.quick.filterprofiler.simple.filter.name">Quick filter...</entry>
<entry key="0_profiler.settings.instrumentation.filter.selectedprofiler.simple.filter.type">0</entry>
<entry key="3_profiler.settings.sort.results.by.thread.cpu.time">false</entry>
<entry key="0_profiler.settings.thread.cpu.timer.on">false</entry>
<entry key="0_profiler.settings.override.jvm.args"/>
<entry key="3_profiler.settings.threads.monitoring.enabled">false</entry>
<entry key="2_profiler.settings.profiling.type">8</entry>
<entry key="0_profiler.settings.settings.name">Monitor Application</entry>
<entry key="0_profiler.settings.code.region.cpu.res.buf.size">1000</entry>
<entry key="2_profiler.settings.profilingpoints.enabled">true</entry>
<entry key="2_profiler.settings.run.gc.on.get.results.in.memory.profiling">true</entry>
</properties>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
For the purpose of easier reading the script
is divided into following sections:
- initialization
- profiling
- applet profiling
-->
<project name="-profiler-impl" default="profile" basedir="..">
<target name="default" depends="profile" description="Build and profile the project."/>
<!--
======================
INITIALIZATION SECTION
======================
-->
<target name="profile-init" depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check"/>
<target name="-profile-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target name="-profile-post-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target name="-profile-init-macrodef-profile">
<macrodef name="resolve">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${env.@{value}}"/>
</sequential>
</macrodef>
<macrodef name="profile">
<attribute name="classname" default="${main.class}"/>
<element name="customize" optional="true"/>
<sequential>
<property environment="env"/>
<resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
<java fork="true" classname="@{classname}" dir="${profiler.info.dir}" jvm="${profiler.info.jvm}">
<jvmarg value="${profiler.info.jvmargs.agent}"/>
<jvmarg line="${profiler.info.jvmargs}"/>
<env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
<arg line="${application.args}"/>
<classpath>
<path path="${run.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper type="glob" from="run-sys-prop.*" to="*"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-profile-init-check" depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile">
<fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
<fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
</target>
<!--
=================
PROFILING SECTION
=================
-->
<target name="profile" if="netbeans.home" depends="profile-init,compile" description="Profile a project in the IDE.">
<nbprofiledirect>
<classpath>
<path path="${run.classpath}"/>
</classpath>
</nbprofiledirect>
<profile/>
</target>
<target name="profile-single" if="netbeans.home" depends="profile-init,compile-single" description="Profile a selected class in the IDE.">
<fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
<nbprofiledirect>
<classpath>
<path path="${run.classpath}"/>
</classpath>
</nbprofiledirect>
<profile classname="${profile.class}"/>
</target>
<!--
=========================
APPLET PROFILING SECTION
=========================
-->
<target name="profile-applet" if="netbeans.home" depends="profile-init,compile-single">
<nbprofiledirect>
<classpath>
<path path="${run.classpath}"/>
</classpath>
</nbprofiledirect>
<profile classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</profile>
</target>
<!--
=========================
TESTS PROFILING SECTION
=========================
-->
<target name="profile-test-single" if="netbeans.home" depends="profile-init,compile-test-single">
<nbprofiledirect>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
</nbprofiledirect>
<junit showoutput="true" fork="true" dir="${profiler.info.dir}" jvm="${profiler.info.jvm}" failureproperty="tests.failed" errorproperty="tests.failed">
<env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
<jvmarg value="${profiler.info.jvmargs.agent}"/>
<jvmarg line="${profiler.info.jvmargs}"/>
<test name="${profile.class}"/>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper type="glob" from="test-sys-prop.*" to="*"/>
</syspropertyset>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
</junit>
</target>
</project>

View File

@@ -0,0 +1,73 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.run.all.processors=true
application.title=Flease
application.vendor=bjko
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/Flease.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
includes=**
jar.compress=false
javac.classpath=\
${reference.XtreemFS-foundation.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
javac.source=1.6
javac.target=1.6
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
project.XtreemFS-foundation=../foundation
reference.XtreemFS-foundation.jar=${project.XtreemFS-foundation}/dist/Foundation.jar
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=-ea
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>Flease</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
<references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
<reference>
<foreign-project>XtreemFS-foundation</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
</references>
</configuration>
</project>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<protobuf-config xmlns="http://tabor.waw.pl/netbeans/protobuf/generator/jaxb" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tabor.waw.pl/netbeans/protobuf/generator/jaxb ProtobufConfig.xsd"><generator on="false" type="cpp"/><generator on="false" type="java"/><generator on="false" type="python"/></protobuf-config>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="JavaApplication5_protobuf" default="default" basedir="." xmlns:s="http://tabor.waw.pl/netbeans/protobuf/generator/jaxb">
<target name="protobuf-environment">
<echo message="user.properties.file:${user.properties.file}"/>
<dirname property="user.properties.dir" file="${user.properties.file}"/>
<echo message="user.properties.dir:${user.properties.dir}"/>
<property file="${user.properties.dir}/config/Preferences/pl/waw/tabor/netbeans/protobuf/generator.properties"/>
<property name="protobuf.executable" value="protoc"/>
<property name="build.generated.sources.dir.protobuf.java" value="${build.generated.sources.dir}/protobuf-java"/>
<property name="build.generated.sources.dir.protobuf.cpp" value="${build.generated.sources.dir}/protobuf-cpp"/>
<property name="build.generated.sources.dir.protobuf.python" value="${build.generated.sources.dir}/protobuf-python"/>
</target>
<target name="protobuf-code-generation" depends="-do-init,-init-macrodef-javac,protobuf-environment">
<fileset dir="${src.dir}" id="proto.classpath">
<include name="**/*.proto"/>
</fileset>
<pathconvert property="protofiles" pathsep=" " refid="proto.classpath"/>
<echo message="${protobuf.executable} -I ${basedir} ${protofiles}"/>
<exec executable="${protobuf.executable}" searchpath="true">
<arg line="-I ${basedir}"/>
<arg line="${protofiles}"/>
</exec>
</target>
</project>

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
/**
* Object represents a lease.
* @author bjko
*/
public class Flease {
public static final Flease EMPTY_LEASE = new Flease(null,null, 0,FleaseMessage.IGNORE_MASTER_EPOCH);
private final ASCIIString leaseHolder;
private final long leaseTimeout_ms;
private final ASCIIString cellId;
private final long masterEpochNumber;
public Flease(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long masterEpochNumber) {
this.cellId = cellId;
this.leaseHolder = leaseHolder;
this.leaseTimeout_ms = leaseTimeout_ms;
this.masterEpochNumber = masterEpochNumber;
}
/**
* @return the leaseHolder
*/
public ASCIIString getLeaseHolder() {
return leaseHolder;
}
/**
* @return the leaseTimeout_ms
*/
public long getLeaseTimeout_ms() {
return leaseTimeout_ms;
}
public boolean isValid() {
return (TimeSync.getGlobalTime() < leaseTimeout_ms);
}
public boolean isEmptyLease() {
return leaseTimeout_ms == 0;
}
public boolean equals(Object other) {
try {
Flease o = (Flease) other;
boolean sameTo = o.leaseTimeout_ms == this.leaseTimeout_ms;
return isSameLeaseHolder(o) && sameTo;
} catch (ClassCastException ex) {
return false;
}
}
public boolean isSameLeaseHolder(Flease o) {
return (o.leaseHolder == this.leaseHolder) ||
(o.leaseHolder != null) && (this.leaseHolder != null) && (o.leaseHolder.equals(this.leaseHolder));
}
/**
* @return the cellId
*/
ASCIIString getCellId() {
return cellId;
}
public String toString() {
return (cellId == null ? "" : cellId.toString())+": "+
(leaseHolder == null ? "null" : leaseHolder.toString())+"/"+
leaseTimeout_ms;
}
/**
* @return the masterEpochNumber
*/
public long getMasterEpochNumber() {
return masterEpochNumber;
}
}

View File

@@ -0,0 +1,191 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import java.net.InetSocketAddress;
import org.xtreemfs.foundation.buffer.ASCIIString;
/**
*
* @author bjko
*/
public class FleaseConfig {
/**
* maximum lease timeout used in the system
*/
private final int maxLeaseTimeout_ms;
/**
* maximum clock drift allowed
*/
private final int dmax_ms;
/**
* used to discard old messages
*/
private final int messageTimeout_ms;
/**
* time the proposer waits for an answer
*/
private final int roundTimeout_ms;
private final int cellTimeout_ms;
private final int restartWait_ms;
private final int senderId;
private final InetSocketAddress endpoint;
private final ASCIIString identity;
private final int maxRetries;
private final boolean sendLearnMessages;
private final int toNotification_ms;
private final boolean debugPrintMessages;
public FleaseConfig(int leaseTimeout_ms, int dmax_ms,
int messageTimeout_ms, InetSocketAddress endpoint,
String identity, int maxRetries) {
this(leaseTimeout_ms,dmax_ms,messageTimeout_ms,endpoint,identity,maxRetries,true,0);
}
public FleaseConfig(int leaseTimeout_ms, int dmax_ms,
int messageTimeout_ms, InetSocketAddress endpoint,
String identity, int maxRetries, boolean sendLearnMessages,
int toNotification_ms) {
this(leaseTimeout_ms, dmax_ms, messageTimeout_ms, endpoint, identity, maxRetries, sendLearnMessages, toNotification_ms, false);
}
public FleaseConfig(int leaseTimeout_ms, int dmax_ms,
int messageTimeout_ms, InetSocketAddress endpoint,
String identity, int maxRetries, boolean sendLearnMessages,
int toNotification_ms, boolean debugPrintMessages) {
this.maxLeaseTimeout_ms = leaseTimeout_ms;
this.dmax_ms = dmax_ms;
this.messageTimeout_ms = messageTimeout_ms;
this.cellTimeout_ms = maxLeaseTimeout_ms*2;
this.roundTimeout_ms = messageTimeout_ms*2;
this.restartWait_ms = maxLeaseTimeout_ms+dmax_ms*2+messageTimeout_ms;
this.endpoint = endpoint;
this.senderId = identity.hashCode();
checkValidConfiguration();
this.identity = new ASCIIString(identity);
this.maxRetries = maxRetries;
this.sendLearnMessages = sendLearnMessages;
this.toNotification_ms = toNotification_ms;
this.debugPrintMessages = debugPrintMessages;
}
public void checkValidConfiguration() {
if (maxLeaseTimeout_ms < dmax_ms*2) {
throw new IllegalArgumentException("maxLeaseTimeout_ms must be at least twice as long as dmax_ms but should be much bigger");
}
if (maxLeaseTimeout_ms < dmax_ms*2+roundTimeout_ms*2) {
throw new IllegalArgumentException("maxLeaseTimeout_ms must be at least as long as dmax_ms*2+4*message_timeout but should be much bigger");
}
}
/**
* @return the leaseTimeout_ms
*/
public int getMaxLeaseTimeout() {
return maxLeaseTimeout_ms;
}
/**
* @return the dmax_ms
*/
public int getDMax() {
return dmax_ms;
}
/**
* @return the maxPxWait_ms
*/
public int getMessageTimeout() {
return messageTimeout_ms;
}
/**
* @return the cellTimeout_ms
*/
public int getCellTimeout() {
return cellTimeout_ms;
}
/**
* @return the restartWait_ms
*/
public int getRestartWait() {
return restartWait_ms;
}
/**
* @return the senderId
*/
public int getSenderId() {
return senderId;
}
/**
* @return the endpoint
*/
public InetSocketAddress getEndpoint() {
return endpoint;
}
public ASCIIString getIdentity() {
return identity;
}
public int getRoundTimeout() {
return roundTimeout_ms;
}
public int getMaxRetries() {
return maxRetries;
}
/**
* @return the sendLearnMessages
*/
public boolean isSendLearnMessages() {
return sendLearnMessages;
}
/**
* @return the toNotification_ms
*/
public int getToNotification_ms() {
return toNotification_ms;
}
/**
* @return the debugPrintMessages
*/
public boolean isDebugPrintMessages() {
return debugPrintMessages;
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.proposer.FleaseException;
import org.xtreemfs.foundation.flease.proposer.FleaseListener;
/**
*
* @author bjko
*/
public class FleaseFuture implements FleaseListener {
private volatile Flease result;
private volatile FleaseException error;
FleaseFuture() {
result = null;
}
public Flease get() throws FleaseException,InterruptedException {
synchronized (this) {
if ((result == null) && (error == null))
this.wait();
if (error != null)
throw error;
return result;
}
}
public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long masterEpochNumber) {
synchronized (this) {
result = new Flease(cellId,leaseHolder,leaseTimeout_ms,masterEpochNumber);
this.notifyAll();
}
}
public void proposalFailed(ASCIIString cellId, Throwable cause) {
synchronized (this) {
if (cause instanceof FleaseException) {
error = (FleaseException) cause;
} else {
error = new FleaseException(cause.getMessage(), cause);
}
this.notifyAll();
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
/**
*
* @author bjko
*/
public interface FleaseMessageSenderInterface {
public void sendMessage(FleaseMessage message, InetSocketAddress recipient);
}

View File

@@ -0,0 +1,691 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.xtreemfs.foundation.LifeCycleThread;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.acceptor.FleaseAcceptor;
import org.xtreemfs.foundation.flease.acceptor.FleaseAcceptorCell;
import org.xtreemfs.foundation.flease.acceptor.LearnEventListener;
import org.xtreemfs.foundation.flease.comm.FleaseCommunicationInterface;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.proposer.FleaseException;
import org.xtreemfs.foundation.flease.proposer.FleaseListener;
import org.xtreemfs.foundation.flease.proposer.FleaseLocalQueueInterface;
import org.xtreemfs.foundation.flease.proposer.FleaseProposer;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
*
* @author bjko
*/
public class FleaseStage extends LifeCycleThread implements LearnEventListener, FleaseLocalQueueInterface {
public static final String FLEASE_VERSION = "0.2.4 (trunk)";
public static final int TIMER_INTERVAL_IN_MS = 50;
public static final boolean ENABLE_TIMEOUT_EVENTS = true;
public static final boolean DISABLE_RENEW_FOR_TESTING = false;
public static final boolean COLLECT_STATISTICS = false;
private final FleaseProposer proposer;
private final FleaseAcceptor acceptor;
private final PriorityQueue<TimerEntry> timers;
private final PriorityQueue<Flease> leaseTimeouts;
private final LinkedBlockingQueue messages;
private volatile boolean quit;
private long lastTimerRun;
private final FleaseConfig config;
private final FleaseMessageSenderInterface sender;
public static final int MAX_BATCH_SIZE = 20;
private final FleaseStatusListener leaseListener;
private final AtomicReference<List<Integer>> durRequests, durMsgs, durTimers;
private final AtomicInteger inRequests, inMsgs, inTimers, outMsgs;
private final FleaseStats statThr;
private final MasterEpochHandlerInterface meHandler;
/**
* Creates a new instance of Flease.
* @param config flease configuration used for all cells and leases.
* @param lockfileDir a lockfile for this flease instance is created in this directory.
* @param sender interface to send flease messages to other flease nodes.
* @param ignoreLockForTesting should only be used by unit tests.
* @param viewListener not used at the moment, can be null.
* @param leaseListener listener is notified when the lease changes for any open cell.
* @param meHandler handler for storing/retrieving master epochs, can be null.
* @throws IOException
*/
public FleaseStage(FleaseConfig config, String lockfileDir,
final FleaseMessageSenderInterface sender, boolean ignoreLockForTesting,
final FleaseViewChangeListenerInterface viewListener, final FleaseStatusListener leaseListener,
final MasterEpochHandlerInterface meHandler) throws IOException {
super("FleaseSt");
assert (sender != null);
assert(leaseListener != null);
timers = new PriorityQueue<TimerEntry>();
messages = new LinkedBlockingQueue();
quit = false;
this.config = config;
this.leaseListener = leaseListener;
this.meHandler = meHandler;
acceptor = new FleaseAcceptor(this, config, lockfileDir, ignoreLockForTesting);
proposer = new FleaseProposer(config, acceptor, new FleaseCommunicationInterface() {
public void sendMessage(FleaseMessage msg, InetSocketAddress receiver) throws IOException {
sender.sendMessage(msg, receiver);
}
public void requestTimer(FleaseMessage msg, long timestamp) {
createTimer(msg, timestamp);
}
}, leaseListener, this, this,meHandler);
acceptor.setViewChangeListener(viewListener);
proposer.setViewChangeListener(viewListener);
this.sender = sender;
leaseTimeouts = new PriorityQueue<Flease>(1000, new Comparator<Flease>() {
public int compare(Flease o1, Flease o2) {
return (int) (o1.getLeaseTimeout_ms() - o2.getLeaseTimeout_ms());
}
});
if (COLLECT_STATISTICS) {
durRequests = new AtomicReference(new LinkedList());
durTimers = new AtomicReference(new LinkedList());
durMsgs = new AtomicReference(new LinkedList());
inRequests = new AtomicInteger();
inTimers = new AtomicInteger();
inMsgs = new AtomicInteger();
outMsgs = new AtomicInteger();
statThr = new FleaseStats(this, lockfileDir+"/flease.stats");
} else {
durRequests = null;
durTimers = null;
durMsgs = null;
outMsgs = null;
inRequests = null;
inTimers = null;
inMsgs = null;
statThr = null;
}
}
public ASCIIString getIdentity() {
return config.getIdentity();
}
@Deprecated
public FleaseFuture openCell(ASCIIString cellId, List<InetSocketAddress> acceptors, boolean requestMasterEpoch) {
return openCell(cellId, acceptors, requestMasterEpoch, 0);
}
/**
* Opens a cell. The leaseListener will be notified of all lease events for this cell. The local flease
* instance will try to acquire the lease.
*
* @param cellId
* unique ID of the cell to open.
* @param acceptors
* list of remote flease instances, do not include local flease instance.
* @param requestMasterEpoch
* if true, a master epoch will be requested when the local instance is lease owner.
* @param viewId
* the current view id to open the cell with.
* @return
*/
public FleaseFuture openCell(ASCIIString cellId, List<InetSocketAddress> acceptors, boolean requestMasterEpoch,
int viewId) {
FleaseFuture f = new FleaseFuture();
Request rq = new Request(Request.RequestType.OPEN_CELL_REQUEST);
rq.cellId = cellId;
rq.acceptors = acceptors;
rq.listener = f;
rq.requestME = requestMasterEpoch;
rq.viewId = viewId;
if (COLLECT_STATISTICS)
inRequests.incrementAndGet();
this.messages.add(rq);
return f;
}
public void batchOpenCells(ASCIIString[] cellIds, List<InetSocketAddress>[] acceptors, boolean requestMasterEpoch) {
List<Request> batch = new ArrayList(cellIds.length);
for (int i =0; i < cellIds.length; i++) {
Request rq = new Request(Request.RequestType.OPEN_CELL_REQUEST);
rq.cellId = cellIds[i];
rq.acceptors = acceptors[i];
rq.listener = null;
rq.requestME = requestMasterEpoch;
batch.add(rq);
}
for (int i = 0; i < batch.size(); i += MAX_BATCH_SIZE) {
int endIndex = i+MAX_BATCH_SIZE;
if (endIndex > batch.size()-1)
endIndex = batch.size();
List<Request> sublist = batch.subList(i, endIndex);
if (COLLECT_STATISTICS)
inRequests.addAndGet(sublist.size());
this.messages.addAll(sublist);
}
}
/**
* Closes a cell which must be open. If the local instance is the current lease owner,
* the lease will not be renewed.
* @param cellId
* @param returnLease if true, the lease will immediately be released.
* @return
*/
public FleaseFuture closeCell(ASCIIString cellId, boolean returnLease) {
// TODO(bjko): return lease, check if not_owner event is triggered.
FleaseFuture f = new FleaseFuture();
Request rq = new Request(Request.RequestType.CLOSE_CELL_REQUEST);
rq.cellId = cellId;
rq.listener = f;
if (COLLECT_STATISTICS)
inRequests.incrementAndGet();
this.messages.add(rq);
return f;
}
public void setViewId(ASCIIString cellId, int viewId, FleaseListener listener) {
Request rq = new Request(Request.RequestType.SET_VIEW);
rq.cellId = cellId;
rq.viewId = viewId;
rq.listener = listener;
if (COLLECT_STATISTICS)
inRequests.incrementAndGet();
this.messages.add(rq);
}
public Map<ASCIIString, FleaseMessage> getLocalState() throws InterruptedException {
final Request rq = new Request(Request.RequestType.GET_STATE);
final Map[] map = new Map[1];
rq.cback = new FleaseStateCallback() {
public void localStateResult(Map<ASCIIString, FleaseMessage> state) {
synchronized (rq) {
map[0] = state;
rq.notifyAll();
}
}
};
this.messages.add(rq);
synchronized (rq) {
if (map[0] == null) {
rq.wait();
}
return map[0];
}
}
public void receiveMessage(FleaseMessage msg) {
assert (msg.getSender() != null);
if (COLLECT_STATISTICS)
inMsgs.incrementAndGet();
this.messages.add(msg);
}
public FleaseMessage _test_get_local_lease_state(ASCIIString cellId) {
return acceptor.getLocalLeaseInformation(cellId);
}
public String _dump_acceptor_state(ASCIIString cellId) {
FleaseAcceptorCell cell = acceptor.cells.get(cellId);
if (cell == null) {
return cellId + ": does not exist";
} else {
return cellId + ": " + cell.toString();
}
}
public void learnedEvent(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long masterEpochNumber) {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this,"learned event: "+leaseHolder+"/"+leaseTimeout_ms);
}
Flease newFlease = new Flease(cellId, leaseHolder, leaseTimeout_ms, masterEpochNumber);
Flease oldFlease = proposer.updatePrevLeaseForCell(cellId, newFlease);
if (oldFlease != null) {
if (oldFlease.isValid()) {
if (!oldFlease.isSameLeaseHolder(newFlease)) {
Logging.logMessage(
Logging.LEVEL_DEBUG,
Category.replication,
this,
"New lease replaced old lease which is still valid according to this OSD's clocks. Make sure all OSD clocks are synchronized. New Lease: %s Old Lease: %s",
newFlease, oldFlease);
}
}
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this,"lease state change: %s %s %d",cellId,leaseHolder,leaseTimeout_ms);
}
leaseListener.statusChanged(cellId, newFlease);
if (ENABLE_TIMEOUT_EVENTS) {
leaseTimeouts.remove(oldFlease);
leaseTimeouts.add(newFlease);
}
}
}
@Override
public void run() {
if (COLLECT_STATISTICS)
statThr.start();
Logging.logMessage(Logging.LEVEL_INFO, Category.replication, this, "Flease (version %s) ready", FLEASE_VERSION);
notifyStarted();
// interval to check the OFT
long nextTimerRunInMS = TIMER_INTERVAL_IN_MS;
lastTimerRun = 0;
List<Object> rqList = new ArrayList(1000);
while (!quit) {
try {
final Object tmp = messages.poll(nextTimerRunInMS, TimeUnit.MILLISECONDS);
if (quit) {
break;
}
if ((tmp == null) ||
(TimeSync.getLocalSystemTime() >= lastTimerRun + nextTimerRunInMS)) {
if (ENABLE_TIMEOUT_EVENTS) {
//nextTimerRunInMS =
checkTimers();
checkLeaseTimeouts();
} else {
nextTimerRunInMS = checkTimers();
}
lastTimerRun = TimeSync.getLocalSystemTime();
}
if (tmp == null) {
continue;
}
rqList.add(tmp);
messages.drainTo(rqList, 25);
/*final int numItems = messages.poll(rqList, 25, nextTimerRunInMS);
if ((numItems == 0) ||
(TimeSync.getLocalSystemTime() >= lastTimerRun+nextTimerRunInMS)) {
nextTimerRunInMS = checkTimers();
lastTimerRun = TimeSync.getLocalSystemTime();
}
if (numItems == 0)
continue;*/
while (!rqList.isEmpty()) {
final Object request = rqList.remove(rqList.size() - 1);
long rqStart;
if (COLLECT_STATISTICS) {
rqStart = System.nanoTime();
}
if (request instanceof FleaseMessage) {
final FleaseMessage msg = (FleaseMessage) request;
if (msg.isInternalEvent()) {
//should never happen!
Logging.logMessage(Logging.LEVEL_ERROR, Category.replication, this, "received internal event: %s", msg);
} else if (msg.isAcceptorMessage()) {
final FleaseMessage response = acceptor.processMessage(msg);
if (response != null) {
if (msg.getMasterEpochNumber() == FleaseMessage.REQUEST_MASTER_EPOCH
&& response.getMsgType() == FleaseMessage.MsgType.MSG_PREPARE_ACK) {
// Respond with the current master epoch.
if (meHandler != null) {
MasterEpochHandlerInterface.Continuation cont = new MasterEpochHandlerInterface.Continuation() {
@Override
public void processingFinished() {
sender.sendMessage(response, msg.getSender());
}
};
meHandler.sendMasterEpoch(response, cont);
} else {
Logging.logMessage(Logging.LEVEL_ERROR, this,
"MASTER EPOCH WAS REQUESTED, BUT NO MASTER EPOCH HANDLER DEFINED!!!");
sender.sendMessage(response, msg.getSender());
}
} else if (msg.getMasterEpochNumber() != FleaseMessage.IGNORE_MASTER_EPOCH
&& response.getMsgType() == FleaseMessage.MsgType.MSG_ACCEPT_ACK) {
// Write the current master epoch to disk.
if (meHandler != null) {
MasterEpochHandlerInterface.Continuation cont = new MasterEpochHandlerInterface.Continuation() {
@Override
public void processingFinished() {
sender.sendMessage(response, msg.getSender());
}
};
meHandler.storeMasterEpoch(response, cont);
}
} else {
sender.sendMessage(response, msg.getSender());
}
}
} else {
proposer.processMessage(msg);
}
if (COLLECT_STATISTICS) {
long rqEnd = System.nanoTime();
durMsgs.get().add(Integer.valueOf((int)(rqEnd-rqStart)));
outMsgs.incrementAndGet();
}
} else {
Request rq = (Request) request;
switch (rq.type) {
case OPEN_CELL_REQUEST: {
assert (rq.acceptors != null);
try {
proposer.openCell(rq.cellId, rq.acceptors, rq.requestME, rq.viewId);
acceptor.setViewId(rq.cellId, rq.viewId);
if (rq.listener != null)
rq.listener.proposalResult(rq.cellId, null, 0, FleaseMessage.IGNORE_MASTER_EPOCH);
} catch (FleaseException ex) {
Logging.logError(Logging.LEVEL_DEBUG, this, ex);
leaseListener.leaseFailed(rq.cellId, ex);
}
break;
}
case CLOSE_CELL_REQUEST: {
proposer.closeCell(rq.cellId);
rq.listener.proposalResult(rq.cellId, null, 0, FleaseMessage.IGNORE_MASTER_EPOCH);
break;
}
case HANDOVER_LEASE: {
try {
Flease prevLease = proposer.updatePrevLeaseForCell(rq.cellId, Flease.EMPTY_LEASE);
if (prevLease != null) {
//cancel the lease
leaseTimeouts.remove(prevLease);
}
proposer.handoverLease(rq.cellId, rq.newLeaseOwner);
} catch (FleaseException ex) {
rq.listener.proposalFailed(rq.cellId, ex);
}
break;
}
case SET_VIEW: {
proposer.setViewId(rq.cellId, rq.viewId);
acceptor.setViewId(rq.cellId, rq.viewId);
rq.listener.proposalResult(rq.cellId, null, 0, FleaseMessage.IGNORE_MASTER_EPOCH);
break;
}
case GET_STATE: {
try {
rq.cback.localStateResult(acceptor.localState());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
if (COLLECT_STATISTICS) {
long rqEnd = System.nanoTime();
durRequests.get().add(Integer.valueOf((int)(rqEnd-rqStart)));
}
}
}
if (DISABLE_RENEW_FOR_TESTING) {
Thread.sleep(0, 2);
}
} catch (InterruptedException ex) {
if (quit) {
break;
}
} catch (Throwable ex) {
notifyCrashed(ex);
break;
}
}
acceptor.shutdown();
notifyStopped();
Logging.logMessage(Logging.LEVEL_INFO, Category.replication, this, "Flease stopped", FLEASE_VERSION);
}
public void shutdown() {
if (COLLECT_STATISTICS)
statThr.shutdown();
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this, "received shutdown call...");
quit = true;
this.interrupt();
}
private int checkTimers() throws Throwable {
final long now = TimeSync.getLocalSystemTime();
TimerEntry e = timers.peek();
if (e == null) {
return TIMER_INTERVAL_IN_MS;
}
if (e.getScheduledTime() <= now + TIMER_INTERVAL_IN_MS) {
//execute timer
do {
e = timers.poll();
long rqStart;
if (COLLECT_STATISTICS) {
rqStart = System.nanoTime();
inTimers.incrementAndGet();
}
if (e.getScheduledTime() < now) {
Logging.logMessage(Logging.LEVEL_DEBUG, this, "event sent after deadline: %s", e.message);
}
e.getMessage().setSendTimestamp(TimeSync.getGlobalTime());
proposer.processMessage(e.getMessage());
if (COLLECT_STATISTICS) {
long rqEnd = System.nanoTime();
durTimers.get().add(Integer.valueOf((int)(rqEnd-rqStart)));
}
e = timers.peek();
if (e == null) {
return TIMER_INTERVAL_IN_MS;
}
} while (e.getScheduledTime() <= now + TIMER_INTERVAL_IN_MS);
return (int) (e.getScheduledTime() - now);
} else {
//tell how long we have to wait
return (int) (e.getScheduledTime() - now);
}
}
private void checkLeaseTimeouts() {
final long now = TimeSync.getGlobalTime();
final long deadline = now + TIMER_INTERVAL_IN_MS + TimeSync.getLocalRenewInterval()+config.getToNotification_ms();
Flease f = leaseTimeouts.peek();
if (f == null)
return;
if (f.getLeaseTimeout_ms() <= deadline) {
//execute timer
do {
f = leaseTimeouts.poll();
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this,"lease state change: %s timed out (old lease: %s)",f.getCellId(),f.toString());
}
proposer.updatePrevLeaseForCell(f.getCellId(), f.EMPTY_LEASE);
leaseListener.statusChanged(f.getCellId(), Flease.EMPTY_LEASE);
//create restart event
FleaseMessage restartEvt = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART);
restartEvt.setCellId(f.getCellId());
restartEvt.setProposalNo(proposer.getCurrentBallotNo(f.getCellId()));
createTimer(restartEvt, TimeSync.getLocalSystemTime() + config.getDMax());
f = leaseTimeouts.peek();
if (f == null) {
return;
}
} while (f.getLeaseTimeout_ms() <= deadline);
}
}
protected void createTimer(FleaseMessage msg, long timestamp) {
msg.validateMessage();
TimerEntry e = new TimerEntry(timestamp, msg);
timers.add(e);
}
int getInRequests() {
return this.inRequests.getAndSet(0);
}
int getInMessages() {
return this.inMsgs.getAndSet(0);
}
int getOutMessages() {
return this.outMsgs.getAndSet(0);
}
int getInTimers() {
return this.inTimers.getAndSet(0);
}
List<Integer> getRequestDurations() {
return durRequests.getAndSet(new LinkedList());
}
List<Integer> getMessageDurations() {
return durMsgs.getAndSet(new LinkedList());
}
List<Integer> getTimersDurations() {
return durTimers.getAndSet(new LinkedList());
}
@Override
public void enqueueMessage(FleaseMessage message) {
messages.add(message);
}
private final static class TimerEntry implements Comparable {
private final long scheduledTime;
private final FleaseMessage message;
public TimerEntry(long scheduledTime, FleaseMessage message) {
this.scheduledTime = scheduledTime;
this.message = message;
}
/**
* @return the scheduledTime
*/
public long getScheduledTime() {
return scheduledTime;
}
public FleaseMessage getMessage() {
return this.message;
}
public int compareTo(Object o) {
TimerEntry e2 = (TimerEntry) o;
return (int) (this.scheduledTime - e2.scheduledTime);
}
}
private final static class Request {
public boolean autoRenew;
public boolean requestME;
public enum RequestType {
OPEN_CELL_REQUEST,
CLOSE_CELL_REQUEST,
GET_LEASE_REQUEST,
RETURN_LEASE_REQUEST,
HANDOVER_LEASE,
GET_STATE,
SET_VIEW
};
public final RequestType type;
public ASCIIString cellId;
public ASCIIString newLeaseOwner; //< for handover only!
public List<InetSocketAddress> acceptors;
public FleaseListener listener;
public int viewId;
public FleaseStateCallback cback;
public Request(RequestType type) {
this.type = type;
}
}
private static interface FleaseStateCallback {
public void localStateResult(Map<ASCIIString, FleaseMessage> state);
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import org.xtreemfs.foundation.flease.comm.tcp.TCPFleaseCommunicator;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
*
* @author bjko
*/
public class FleaseStats extends Thread {
public static final int INTERVAL_IN_MS = 1000;
private volatile boolean quit;
private final FleaseStage st;
private final PrintWriter out;
public FleaseStats(FleaseStage st, String logfile) throws IOException {
super("FStats");
this.st = st;
this.quit = false;
try {
out = new PrintWriter(logfile);
} catch (IOException ex) {
Logging.logMessage(Logging.LEVEL_ERROR, Category.replication, this,"cannot write to %s, due to %s",logfile,ex.toString());
ex.printStackTrace();
throw ex;
}
}
public void shutdown() {
quit = true;
this.interrupt();
}
public void run() {
long t = 0;
Logging.logMessage(Logging.LEVEL_INFO, Category.replication, this,"collecting statistics");
do {
try {
try {
sleep(INTERVAL_IN_MS);
} catch (InterruptedException ex) {
Logging.logMessage(Logging.LEVEL_INFO, this,"interrupted");
break;
}
t += INTERVAL_IN_MS;
int inRq = st.getInRequests();
int inMsgs = st.getInMessages();
int outMsgs = st.getOutMessages();
int inTimers = st.getInTimers();
int tcpOut = TCPFleaseCommunicator.instance.getNumOut();
int tcpIn = TCPFleaseCommunicator.instance.getNumIn();
List<Integer> durRq = st.getRequestDurations();
List<Integer> durMsgs = st.getMessageDurations();
List<Integer> durTimers = st.getTimersDurations();
printValues(inRq, durRq,t,"R");
printValues(inMsgs, durMsgs,t,"M");
printValues2(inMsgs, outMsgs,t,"m");
printValues2(tcpIn, tcpOut,t,"x");
printValues(inTimers, durTimers,t,"T");
} catch (Throwable thr) {
Logging.logMessage(Logging.LEVEL_ERROR, Category.replication, this,thr.toString());
}
} while (!quit);
out.close();
Logging.logMessage(Logging.LEVEL_INFO, Category.replication, this,"done");
}
void printValues(int numRq, List<Integer> durations, long t, String type) {
int p95_out = getP95(durations);
double outPerInterval = ((double)INTERVAL_IN_MS)/( ((double)p95_out) / 1e6);
double rho = ((double)numRq)/outPerInterval;
if (p95_out == 0) {
outPerInterval = 0;
rho = 0;
}
out.format("%10d %s %10.2f %10.2f %10.2f\n", t,type,(double)numRq,outPerInterval,rho);
}
void printValues2(int numRq, int numOut, long t, String type) {
double rho = ((double)numRq)/((double)numOut);
if (numOut == 0) {
rho = 0;
}
out.format("%10d %s %10.2f %10.2f %10.2f\n", t,type,(double)numRq,(double)numOut,rho);
}
int getP95(List<Integer> items) {
if (items.size() == 0)
return 0;
if (items.size() == 1)
return items.get(0);
Collections.sort(items);
int rank = ((int)Math.round(0.95*items.size()))-1;
return items.get(rank);
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.proposer.FleaseException;
/**
*
* @author bjko
*/
public interface FleaseStatusListener {
public void statusChanged(ASCIIString cellId, Flease lease);
public void leaseFailed(ASCIIString cellId, FleaseException error);
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import org.xtreemfs.foundation.buffer.ASCIIString;
/**
* The view change listener is called whenever flease
* (proposor or acceptor) see a new viewId > current viewId
* @author bjko
*/
public interface FleaseViewChangeListenerInterface {
public void viewIdChangeEvent(ASCIIString cellId, int viewId);
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
/**
*
* @author bjko
*/
public interface MasterEpochHandlerInterface {
public void sendMasterEpoch(FleaseMessage response, Continuation callback);
public void storeMasterEpoch(FleaseMessage request, Continuation callback);
public static interface Continuation {
void processingFinished();
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.concurrent.LinkedBlockingQueue;
import org.xtreemfs.foundation.LRUCache;
import org.xtreemfs.foundation.LifeCycleThread;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.logging.Logging;
/**
*
* @author bjko
*/
public class SimpleMasterEpochHandler extends LifeCycleThread implements MasterEpochHandlerInterface {
public static final int MAX_EPOCH_CACHE_SIZE = 10000;
private final LinkedBlockingQueue<Request> requests;
private final LRUCache<ASCIIString,Long> epochs;
private final String directory;
public SimpleMasterEpochHandler(String directory) {
super("SimpleMEHandler");
requests = new LinkedBlockingQueue<Request>();
epochs = new LRUCache<ASCIIString, Long>(MAX_EPOCH_CACHE_SIZE);
this.directory = directory;
}
@Override
public void run() {
try {
notifyStarted();
do {
Request rq = requests.take();
switch (rq.type) {
case SEND: {
try {
Long epoch = epochs.get(rq.message.getCellId());
if (epoch == null) {
File f = new File(getFileName(rq.message.getCellId()));
if (f.exists()) {
RandomAccessFile raf = new RandomAccessFile(f, "r");
epoch = raf.readLong();
raf.close();
} else {
epoch = 0l;
}
epochs.put(rq.message.getCellId(),epoch);
Logging.logMessage(Logging.LEVEL_DEBUG, Logging.Category.all, this, "sent %d", epoch);
}
rq.message.setMasterEpochNumber(epoch);
} catch (Exception ex) {
rq.message.setMasterEpochNumber(-1);
} finally {
try {
rq.callback.processingFinished();
} catch (Exception ex) {
Logging.logError(Logging.LEVEL_ERROR, this, ex);
}
}
break;
}
case STORE: {
try {
File f = new File(getFileName(rq.message.getCellId()));
RandomAccessFile raf = new RandomAccessFile(f, "rw");
raf.writeLong(rq.message.getMasterEpochNumber());
raf.getFD().sync();
raf.close();
Logging.logMessage(Logging.LEVEL_DEBUG, Logging.Category.all, this, "stored %d",
rq.message.getMasterEpochNumber());
epochs.put(rq.message.getCellId(),rq.message.getMasterEpochNumber());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
rq.callback.processingFinished();
} catch (Exception ex) {
Logging.logError(Logging.LEVEL_ERROR, this, ex);
}
}
break;
}
}
} while (!interrupted());
} catch (InterruptedException ex) {
} catch (Throwable ex) {
notifyCrashed(ex);
}
notifyStopped();
}
private String getFileName(ASCIIString cellId) {
return directory + cellId.toString() + ".me";
}
@Override
public void shutdown() {
this.interrupt();
}
@Override
public void sendMasterEpoch(FleaseMessage response, Continuation callback) {
Request rq = new Request();
rq.callback = callback;
rq.message = response;
rq.type = Request.RequestType.SEND;
requests.add(rq);
}
@Override
public void storeMasterEpoch(FleaseMessage request, Continuation callback) {
Request rq = new Request();
rq.callback = callback;
rq.message = request;
rq.type = Request.RequestType.STORE;
requests.add(rq);
}
private final static class Request {
FleaseMessage message;
Continuation callback;
String fileName;
enum RequestType {
SEND, STORE;
};
RequestType type;
}
}

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.xtreemfs.foundation.LifeCycleThread;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
*
* @author bjko
*/
public class UDPFleaseCommunicator extends LifeCycleThread implements FleaseMessageSenderInterface {
private final FleaseStage stage;
private final int port;
private DatagramChannel channel;
private Selector selector;
private volatile boolean quit;
private final AtomicBoolean sendMode;
private final LinkedBlockingQueue<FleaseMessage> q;
private static final int MAX_UDP_SIZE = 16*1024;
private long numTx,numRx;
public UDPFleaseCommunicator(FleaseConfig config, String lockfileDir,
boolean ignoreLockForTesting,
final FleaseViewChangeListenerInterface viewListener) throws Exception {
super("FlUDPCom");
stage = new FleaseStage(config, lockfileDir, this, ignoreLockForTesting, viewListener, null, null);
port = config.getEndpoint().getPort();
q = new LinkedBlockingQueue<FleaseMessage>();
sendMode = new AtomicBoolean(false);
numTx = 0;
numRx = 0;
}
public FleaseStage getStage() {
return stage;
}
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
FleaseMessage m = message.clone();
m.setSender(recipient);
send(m);
}
/**
* sends a UDPRequest.
*
* @attention Overwrites the first byte of rq.data with the message type.
*/
public void send(FleaseMessage rq) {
q.add(rq);
if (q.size() == 1) {
//System.out.println("wakeup!");
selector.wakeup();
}
}
public void shutdown() {
quit = true;
interrupt();
}
@Override
public void run() {
long numRxCycles = 0;
long durAllRx = 0;
long maxPkgCycle = 0;
long avgPkgCycle = 0;
try {
selector = Selector.open();
channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(port));
channel.socket().setReceiveBufferSize(1024*1024*1024);
channel.socket().setSendBufferSize(1024*1024*1024);
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,"sendbuffer size: "+channel.socket().getSendBufferSize());
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,"recv size: "+channel.socket().getReceiveBufferSize());
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
if (Logging.isInfo())
Logging.logMessage(Logging.LEVEL_INFO, Category.net, this, "UDP socket on port %d ready",
port);
stage.start();
stage.waitForStartup();
notifyStarted();
boolean isRdOnly = true;
List<FleaseMessage> sendList = new ArrayList(5000);
ReusableBuffer data = BufferPool.allocate(MAX_UDP_SIZE);
while (!quit) {
if (q.size() == 0) {
if (!isRdOnly) {
channel.keyFor(selector).interestOps(SelectionKey.OP_READ);
//System.out.println("read only");
isRdOnly = true;
}
} else {
if (isRdOnly) {
channel.keyFor(selector).interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//System.out.println("read write");
isRdOnly = false;
}
}
int numKeys = selector.select();
if (q.size() == 0) {
if (!isRdOnly) {
channel.keyFor(selector).interestOps(SelectionKey.OP_READ);
//System.out.println("read only");
isRdOnly = true;
}
} else {
if (isRdOnly) {
channel.keyFor(selector).interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//System.out.println("read write");
isRdOnly = false;
}
}
if (numKeys == 0)
continue;
if (q.size() > 10000) {
System.out.println("QS!!!!! " + q.size());
System.out.println("is readOnly: " + isRdOnly);
}
// fetch events
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
// process all events
while (iter.hasNext()) {
SelectionKey key = iter.next();
// remove key from the list
iter.remove();
if (key.isWritable()) {
q.drainTo(sendList,50);
//System.out.println("sent: "+queue.size());
while (!sendList.isEmpty()) {
FleaseMessage r = sendList.remove(sendList.size()-1);
if (r == null)
break;
if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"sent packet to %s", r.getSender().toString());
data.clear();
r.serialize(data);
data.flip();
int sent = channel.send(data.getBuffer(), r.getSender());
if (sent == 0) {
System.out.println("cannot send anymore!");
q.addAll(sendList);
sendList.clear();
break;
}
numTx++;
}
}
if (key.isReadable()) {
InetSocketAddress sender = null;
int numRxInCycle = 0;
do {
data.clear();
sender = (InetSocketAddress) channel.receive(data.getBuffer());
if (sender == null) {
if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"read key for empty read");
break;
} else {
numRxInCycle++;
if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"read data from %s", sender.toString());
try {
//unpack flease message
data.flip();
FleaseMessage m = new FleaseMessage(data);
m.setSender(sender);
numRx++;
stage.receiveMessage(m);
} catch (Throwable ex) {
ex.printStackTrace();
Logging.logMessage(Logging.LEVEL_WARN, Category.net, this,
"received invalid UPD message: "+ex);
}
}
} while (sender != null);
numRxCycles++;
avgPkgCycle += numRxInCycle;
if (numRxInCycle > maxPkgCycle)
maxPkgCycle = numRxInCycle;
}
}
}
stage.shutdown();
selector.close();
channel.close();
} catch (ClosedByInterruptException ex) {
// ignore
} catch (IOException ex) {
Logging.logError(Logging.LEVEL_ERROR, this, ex);
} catch (Throwable th) {
notifyCrashed(th);
return;
}
Logging.logMessage(Logging.LEVEL_ERROR, Category.net, this,"num packets tranferred: %d tx %d rx",numTx,numRx);
Logging.logMessage(Logging.LEVEL_ERROR, Category.net, this,"numRxCycles %d, maxPkgPerCycle %d, avg/Cycle %d",numRxCycles,maxPkgCycle,avgPkgCycle/numRxCycles);
notifyStopped();
}
}

View File

@@ -0,0 +1,412 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.acceptor;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.FleaseConfig;
import org.xtreemfs.foundation.flease.FleaseViewChangeListenerInterface;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.comm.ProposalNumber;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
* Acceptor for MultiPaXos Lease negotiation (MPXLN).
* This version has no persistent state.
*
* @author bjko
*/
public class FleaseAcceptor {
/**
* Instances of the Multipaxos
*/
public final Map<ASCIIString, FleaseAcceptorCell> cells;
/**
* filename to use for storing state permanantly
*/
public static final String LOCKFILE_NAME = "flease_lock.";
/**
* lockfile full path
*/
private final String lockfile;
private final long waitUntilTimestamp_ms;
/**
* set to true to quit
*/
public boolean quit;
private final FleaseConfig config;
private FleaseViewChangeListenerInterface viewListener;
private final LearnEventListener evtListener;
/**
* Creates a new instance of PxAcceptor
*
* @param port
* port to listen on
* @param debug
*/
public FleaseAcceptor(LearnEventListener evtListener, FleaseConfig localConfig, String lockfileDir, boolean ignoreLockFileForTesting)
throws IOException {
this.config = localConfig;
cells = new HashMap<ASCIIString, FleaseAcceptorCell>();
quit = false;
lockfile = lockfileDir+"/"+LOCKFILE_NAME+config.getIdentity().hashCode();
this.evtListener = evtListener;
File lock = new File(lockfile);
if (lock.exists() && !ignoreLockFileForTesting) {
/*waitUntilTimestamp_ms = TimeSync.getLocalSystemTime()+TimeSync.getLocalRenewInterval()+
config.getRestartWait();*/
waitUntilTimestamp_ms = System.currentTimeMillis() + config.getRestartWait();
Logging.logMessage(Logging.LEVEL_INFO, Category.replication, this,"restarted after crash (lock file %s exists). acceptor will ignore all messages for %d ms (recovery period until %s)",
lockfile,config.getRestartWait(),(new Date(waitUntilTimestamp_ms)).toString());
} else {
waitUntilTimestamp_ms = 0;
if (ignoreLockFileForTesting)
lock.delete();
if (!lock.createNewFile())
throw new IOException("Lock file exists!");
}
}
public void setViewChangeListener(FleaseViewChangeListenerInterface listener) {
viewListener = listener;
}
public void setViewId(ASCIIString cellId, int viewId) {
FleaseAcceptorCell cell = getCell(cellId);
// Set the viewId or invalidate the cell if the VIEW_ID_INVALIDATED is passed.
if (viewId == FleaseMessage.VIEW_ID_INVALIDATED) {
cell.invalidateView();
} else {
cell.setViewId(viewId);
}
}
private FleaseAcceptorCell getCell(FleaseMessage msg) {
assert (msg != null);
return getCell(msg.getCellId());
}
private FleaseAcceptorCell getCell(ASCIIString cellId) {
FleaseAcceptorCell cc = cells.get(cellId);
if (cc == null) {
cc = new FleaseAcceptorCell();
cells.put(cellId,cc);
} else {
if ((cc.lastAccess+config.getCellTimeout()) < System.currentTimeMillis()) {
if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A GCed cell "+cellId);
// Cell is outdated and GCed.
// Create a new cell and transfer the previous view.
FleaseAcceptorCell tmp = new FleaseAcceptorCell();
tmp.setViewId(cc.getViewId());
if (cc.isViewInvalidated()) {
tmp.invalidateView();
}
cells.put(cellId, tmp);
cc = tmp;
}
}
/*if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG,this,"using cell "+cellId);*/
cc.touch();
return cc;
}
/**
* Handles paxos prepare messages
*
* @param msg
* the incomming message
* @return a response message
*/
public FleaseMessage handlePREPARE(FleaseMessage msg) {
final FleaseAcceptorCell cc = getCell(msg);
cc.touch();
if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))) {
if (Logging.isDebug() && config.isDebugPrintMessages()) {
final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString();
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A prepare NACK p:"+preped+" is after "+msg.getProposalNo()+"");
}
FleaseMessage reject = new FleaseMessage(
FleaseMessage.MsgType.MSG_PREPARE_NACK,msg);
reject.setPrevProposalNo(cc.getPrepared().getProposalNo());
reject.setLeaseHolder(null);
reject.setLeaseTimeout(0);
reject.setSendTimestamp(TimeSync.getGlobalTime());
return reject;
} else {
if (Logging.isDebug() && config.isDebugPrintMessages()) {
final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString();
final String acced = (cc.getAccepted() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getAccepted().getProposalNo()+"="+cc.getAccepted().getLeaseHolder()+"/"+cc.getAccepted().getLeaseTimeout();
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A prepare ACK p:"+preped+" -> "+msg.getProposalNo()+" a:"+acced);
}
// lastPrepared = msg;
cc.setPrepared(msg);
// FIXME:Persistently write to disk
FleaseMessage response = new FleaseMessage(
FleaseMessage.MsgType.MSG_PREPARE_ACK,msg);
if (cc.getAccepted() != null) {
response.setPrevProposalNo(cc.getAccepted().getProposalNo());
response.setLeaseHolder(cc.getAccepted().getLeaseHolder());
assert(response.getLeaseHolder() != null);
response.setLeaseTimeout(cc.getAccepted()
.getLeaseTimeout());
}
response.setSendTimestamp(TimeSync.getGlobalTime());
return response;
}
}
/**
* Handles paxos accept (vote) messages.
*
* @param msg
* incomming message
* @return a response message or null
*/
public FleaseMessage handleACCEPT(FleaseMessage msg) {
final FleaseAcceptorCell cc = getCell(msg);
cc.touch();
if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))) {
// reject the request
if (Logging.isDebug() && config.isDebugPrintMessages()) {
final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString();
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A accept NACK p:"+preped+" is after "+msg.getProposalNo()+"");
}
FleaseMessage tmp = new FleaseMessage(
FleaseMessage.MsgType.MSG_ACCEPT_NACK,msg);
tmp.setSendTimestamp(TimeSync.getGlobalTime());
tmp.setLeaseHolder(null);
tmp.setLeaseTimeout(0);
tmp.setPrevProposalNo(cc.getPrepared().getProposalNo());
return tmp;
} else {
// okay accept it
if (Logging.isDebug() && config.isDebugPrintMessages()) {
final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString();
final String acced = (cc.getAccepted() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getAccepted().getProposalNo()+"="+cc.getAccepted().getLeaseHolder()+"/"+cc.getAccepted().getLeaseTimeout();
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A accept ACK p:"+preped+" a: "+acced+" -> "+msg.getProposalNo()+"="+msg.getLeaseHolder()+"/"+msg.getLeaseTimeout());
}
assert(msg.getLeaseHolder() != null);
cc.setAccepted(msg);
cc.setPrepared(msg);
FleaseMessage tmp = new FleaseMessage(
FleaseMessage.MsgType.MSG_ACCEPT_ACK,msg);
tmp.setSendTimestamp(TimeSync.getGlobalTime());
return tmp;
}
}
/**
* Handles paxos learn messages. Removes oudated instances and updates
* maxLearnedInstId accordingly
*
* @param msg
* incomming message
*/
public void handleLEARN(FleaseMessage msg) {
final FleaseAcceptorCell cc = getCell(msg);
cc.touch();
if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))
|| (cc.getAccepted() != null) && (cc.getAccepted().after(msg))) {
if (Logging.isDebug() && config.isDebugPrintMessages())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A ignore outdated LEARN message "+msg.getProposalNo());
} else {
if (Logging.isDebug() && config.isDebugPrintMessages()) {
final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString();
final String acced = (cc.getAccepted() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getAccepted().getProposalNo()+"="+cc.getAccepted().getLeaseHolder()+"/"+cc.getAccepted().getLeaseTimeout();
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication,this,"A learn p:"+preped+" a: "+acced+" -> "+msg.getProposalNo()+"="+msg.getLeaseHolder()+"/"+msg.getLeaseTimeout());
}
cc.setAccepted(msg);
cc.setPrepared(msg);
cc.setLatestLearn(msg);
evtListener.learnedEvent(msg.getCellId(), msg.getLeaseHolder(), msg.getLeaseTimeout(), msg.getMasterEpochNumber());
}
}
/**
* Handles requests for lease information. Returns current lease
* holder+timeout or the current instance id.
*
* @param msg
* incomming message
* @return a response message
*/
public FleaseMessage getLocalLeaseInformation(ASCIIString cellId) {
FleaseAcceptorCell cc = getCell(cellId);
return cc.getLatestLearn();
}
public Map<ASCIIString,FleaseMessage> localState() {
Map<ASCIIString,FleaseMessage> state = new HashMap();
for (ASCIIString cellId : cells.keySet()) {
FleaseAcceptorCell cell = cells.get(cellId);
FleaseMessage lrn = null;
if (cell.isLearned())
lrn = cell.getAccepted();
state.put(cellId, lrn);
}
return state;
}
/**
* main loop
*/
public FleaseMessage processMessage(FleaseMessage msg) {
assert(!quit);
/*if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG,this,"received %s",msg.toString());*/
final long now = TimeSync.getLocalSystemTime();
if (msg.getSendTimestamp()+config.getMessageTimeout() < TimeSync.getGlobalTime()) {
//old message, ignore
if (Logging.isDebug() && config.isDebugPrintMessages())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this,"A outdated message discarded: %s",msg.toString());
return null;
}
if (this.waitUntilTimestamp_ms >= now) {
if (Logging.isDebug() && config.isDebugPrintMessages())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this,"A message discarded, acceptor is still in recovery period");
return null;
}
assert(msg.getCellId() != null);
final FleaseAcceptorCell cc = getCell(msg.getCellId());
if (cc.getViewId() < msg.getViewId()) {
// If the local view is lower than the delivered one, the view listener has to be informed to update
// the local view. But the request can still be answered.
viewListener.viewIdChangeEvent(msg.getCellId(), msg.getViewId());
} else if (cc.getViewId() > msg.getViewId() || (cc.getViewId() == msg.getViewId() && cc.isViewInvalidated())) {
// If the request is from an older view, or the a view that has been invalidated on this
// AcceptorCell, the request has to be aborted.
FleaseMessage response = new FleaseMessage(FleaseMessage.MsgType.MSG_WRONG_VIEW, msg);
response.setViewId(cc.getViewId());
return response;
}
FleaseMessage response = null;
if (msg.getMsgType() == FleaseMessage.MsgType.MSG_PREPARE)
response = handlePREPARE(msg);
else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_ACCEPT)
response = handleACCEPT(msg);
else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_LEARN)
handleLEARN(msg);
/*else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_GET_LEASE)
response = handleGETLEASE(msg);
else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_RENEW_LEASE)
response = handleRENEWINSTANCE(msg);*/
else
Logging.logMessage(Logging.LEVEL_ERROR, Category.replication,this,"A invalid message type received: %s",msg.toString());
/*if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG,this,"response %s",(response != null) ? response.toString() : "<empty>");*/
return response;
}
/*private void notifyLeaseListener(FleaseAcceptorCell cell, ASCIIString leaseHolder, long leaseTimeout) {
if (leaseListener != null) {
final ASCIIString prevLeaseHolder = cell.getPrevLeaseHolder();
if ( ( (((prevLeaseHolder == null) || (leaseHolder == null)) && (prevLeaseHolder != leaseHolder)) ||
(!prevLeaseHolder.equals(leaseHolder)) ) || (leaseTimeout != cell.getPrevLeaseTimeout())) {
leaseListener.statusChanged(cell.getCellId(), leaseHolder,leaseTimeout);
cell.setPrevLeaseHolder(leaseHolder);
cell.setPrevLeaseTimeout(leaseTimeout);
}
}
}*/
/**
* string representation
*
* @return a string
*/
public String toString() {
return "Acceptor @ " + config.getIdentity();
}
// only for testing!
/*public String getLocalLeaseInfo(String cellId) {
synchronized (cells) {
FleaseAcceptorCell cc = getCell(cellId);
FleaseInstance currentL = cc.getInstances().get(cc.getMaxLearnedInstanceId());
if (currentL != null) {
// there is an instance
if (currentL.getAccepted().getLeaseTimeout() > (System
.currentTimeMillis() / 1000)
- config.getDMax()) {
return currentL.getAccepted().getLeaseHolder();
} else {
return null;
}
}
return null;
}
}*/
public void shutdown() {
this.quit = true;
File f = new File(lockfile);
f.delete();
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.acceptor;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicReference;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
/**
* A coordination cell is used to separate concurrent lease nogitiations
* for individual objects (e.g. volumes on the MRC).
* @author bjko
*/
public class FleaseAcceptorCell implements Serializable {
FleaseMessage prepared;
FleaseMessage accepted;
AtomicReference<FleaseMessage> latestLearn;
/** timestamp for last access **/
public long lastAccess;
private int viewId;
private boolean viewInvalidated = false;
/**
* Creates a new instance of CoordinationCell
*/
public FleaseAcceptorCell() {
prepared = null;
accepted = null;
lastAccess = TimeSync.getLocalSystemTime();
latestLearn = new AtomicReference<FleaseMessage>();
}
public FleaseMessage getLatestLearn() {
return latestLearn.get();
}
public void setLatestLearn(FleaseMessage msg) {
assert(msg.getMsgType() == FleaseMessage.MsgType.MSG_LEARN);
latestLearn.set(msg);
}
/**
* Getter for property lastPrep.
* @return Value of property lastPrep.
*/
public FleaseMessage getPrepared() {
return this.prepared;
}
/**
* Setter for property lastPrep.
* @param lastPrep New value of property lastPrep.
*/
public void setPrepared(FleaseMessage prepared) {
this.prepared = prepared;
}
/**
* Getter for property accepted.
* @return Value of property accepted.
*/
public FleaseMessage getAccepted() {
return this.accepted;
}
/**
* Setter for property accepted.
* @param accepted New value of property accepted.
*/
public void setAccepted(FleaseMessage accepted) {
assert(accepted.getLeaseHolder() != null);
assert(accepted.getLeaseTimeout() > 0);
this.accepted = accepted;
}
public boolean isLearned() {
return latestLearn.get() != null;
}
public void touch() {
this.lastAccess = System.currentTimeMillis();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\t");
sb.append("prep ");
sb.append(getPrepared());
sb.append("\n");
sb.append("\t");
sb.append("accept ");
sb.append(getAccepted());
sb.append("\n");
sb.append("\t");
sb.append("isLrnd ");
sb.append(isLearned());
sb.append("\n");
return sb.toString();
}
/**
* @return The most recently set viewId.
*/
public int getViewId() {
return viewId;
}
/**
* Set the acceptors viewId and clears the viewInvalidated flag.
*
* @param viewId
* The viewId to set.
*/
public void setViewId(int viewId) {
this.viewId = viewId;
this.viewInvalidated = false;
}
/**
* @return true if this view is invalidated.
*/
public boolean isViewInvalidated() {
return viewInvalidated;
}
/**
* Invalidate the current view.
*/
public void invalidateView() {
viewInvalidated = true;
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.acceptor;
import java.io.Serializable;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
/**
*
* @author bjko
*/
public class FleaseInstance implements Serializable {
/** Creates a new instance of PxInstance */
public FleaseInstance() {
learned = false;
timeout = 0;
prepared = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE);
accepted = null;
}
/**
* Holds value of property learned.
*/
private boolean learned;
/**
* Getter for property learned.
* @return Value of property learned.
*/
public boolean isLearned() {
return this.learned;
}
/**
* Setter for property learned.
* @param learned New value of property learned.
*/
public void setLearned(boolean learned) {
this.learned = learned;
}
/**
* Holds value of property timeout.
*/
private long timeout;
/**
* Getter for property timeout.
* @return Value of property timeout.
*/
public long getTimeout() {
return this.timeout;
}
/**
* Setter for property timeout.
* @param timeout New value of property timeout.
*/
public void setTimeout(long timeout) {
this.timeout = timeout;
}
/**
* Holds value of property prepared.
*/
private FleaseMessage prepared;
/**
* Getter for property lastPrep.
* @return Value of property lastPrep.
*/
public FleaseMessage getPrepared() {
return this.prepared;
}
/**
* Setter for property lastPrep.
* @param lastPrep New value of property lastPrep.
*/
public void setPrepared(FleaseMessage prepared) {
this.prepared = prepared;
}
/**
* Holds value of property accepted.
*/
private FleaseMessage accepted;
/**
* Getter for property accepted.
* @return Value of property accepted.
*/
public FleaseMessage getAccepted() {
return this.accepted;
}
/**
* Setter for property accepted.
* @param accepted New value of property accepted.
*/
public void setAccepted(FleaseMessage accepted) {
assert(accepted.getLeaseHolder() != null);
assert(accepted.getLeaseTimeout() > 0);
this.accepted = accepted;
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.acceptor;
import org.xtreemfs.foundation.buffer.ASCIIString;
/**
*
* @author bjko
*/
public interface LearnEventListener {
public void learnedEvent(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long masterEpochNumber);
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm;
import java.io.IOException;
import java.net.InetSocketAddress;
/**
*
* @author bjko
*/
public interface FleaseCommunicationInterface {
public void sendMessage(FleaseMessage msg, InetSocketAddress receiver) throws IOException;
public void requestTimer(FleaseMessage msg, long timestamp);
}

View File

@@ -0,0 +1,460 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.Date;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.flease.FleaseConfig;
/**
* A message for multipaxos lease negotiation.
* @author bjko
*/
public class FleaseMessage implements Serializable, Cloneable {
/**
* Message types
*/
public static enum MsgType {
/**
* paxos prepare message
*/
MSG_PREPARE,
/**
* acknowledgment for prepare
*/
MSG_PREPARE_ACK,
/**
* reject of prepare
*/
MSG_PREPARE_NACK,
/**
* paxos vote message
*/
MSG_ACCEPT,
/**
* acceptance of vote (voted)
*/
MSG_ACCEPT_ACK,
/**
* reject of vote message
*/
MSG_ACCEPT_NACK,
/**
* paxos learn message
*/
MSG_LEARN,
/**
* for future use (volontary lease return by master, revocation)
*/
MSG_LEASE_RETURN,
/**
* internal timeout event during prepare (timer)
*/
EVENT_TIMEOUT_PREPARE,
/**
* internal timeout event during prepare (timer)
*/
EVENT_TIMEOUT_ACCEPT,
/**
* internal restart event (timer)
*/
EVENT_RESTART,
/**
* event to renew the lease
*/
EVENT_RENEW,
/**
* message (response) indicating that the viewId has changed
*/
MSG_WRONG_VIEW
};
private static final long serialVersionUID = 3187504351237849866L;
public static final int VIEW_ID_INVALIDATED = -1;
public static final long IGNORE_MASTER_EPOCH = -1;
public static final long REQUEST_MASTER_EPOCH = 0;
/**
* message type
* @see MsgType
*/
private final MsgType msgType;
/**
* cellId this message belongs to
*/
private ASCIIString cellId;
/**
* proposal number for this message
*/
private ProposalNumber proposalNo;
/**
* timestamp when the message was sent to discard messages arriving after
* timeout+dmax.
*/
private long sendTimestamp;
/**
* the socket address of the current lease holder
* part of the proposal value
* @attention necessary for correct operation of leases negotiation
*/
private ASCIIString leaseHolder;
/**
* (absolute) timestamp of lease timeout in ms since epoch
* part of the proposal value
* @attention necessary for correct operation of leases negotiation
*/
private long leaseTimeout;
private ProposalNumber prevProposalNo;
private InetSocketAddress address;
private int viewId;
private long masterEpochNumber;
/**
* Creates a new instance of PxMessage
* @param msgType message type
*/
public FleaseMessage(MsgType msgType) {
this.msgType = msgType;
this.proposalNo = ProposalNumber.EMPTY_PROPOSAL_NUMBER;
this.prevProposalNo = ProposalNumber.EMPTY_PROPOSAL_NUMBER;
this.masterEpochNumber = IGNORE_MASTER_EPOCH;
}
/**
* Creates a new instance of PxMessage
* @param msgType message type
* @param template a message to take instanceId and cellId from
*/
public FleaseMessage(MsgType msgType, FleaseMessage template) {
this.msgType = msgType;
this.proposalNo = template.proposalNo;
this.cellId = template.cellId;
this.leaseHolder = template.leaseHolder;
this.leaseTimeout = template.leaseTimeout;
this.prevProposalNo = template.prevProposalNo;
this.viewId = template.viewId;
this.masterEpochNumber = template.masterEpochNumber;
}
public FleaseMessage(FleaseMessage other) {
this.msgType = other.msgType;
this.address = other.address;
this.proposalNo = other.proposalNo;
this.cellId = other.cellId;
this.leaseHolder = other.leaseHolder;
this.leaseTimeout = other.leaseTimeout;
this.sendTimestamp = other.sendTimestamp;
this.prevProposalNo = other.prevProposalNo;
this.viewId = other.viewId;
this.masterEpochNumber = other.masterEpochNumber;
}
public void validateMessage() {
assert(msgType != null);
assert(proposalNo != null);
assert(cellId != null);
}
/**
* @return the prevAcceptedBallotNo
*/
public ProposalNumber getPrevProposalNo() {
return prevProposalNo;
}
/**
* @param prevAcceptedBallotNo the prevAcceptedBallotNo to set
*/
public void setPrevProposalNo(ProposalNumber prevAcceptedBallotNo) {
this.prevProposalNo = prevAcceptedBallotNo;
}
/**
* @return the viewId
*/
public int getViewId() {
return viewId;
}
/**
* @param viewId the viewId to set
*/
public void setViewId(int viewId) {
this.viewId = viewId;
}
/**
* @return the masterEpochNumber
*/
public long getMasterEpochNumber() {
return masterEpochNumber;
}
/**
* @param masterEpochNumber the masterEpochNumber to set
*/
public void setMasterEpochNumber(long masterEpochNumber) {
this.masterEpochNumber = masterEpochNumber;
}
/**
* Getter for property proposalNo.
* @return Value of property proposalNo.
*/
public ProposalNumber getProposalNo() {
return this.proposalNo;
}
/**
* Setter for property proposalNo.
* @param proposalNo New value of property proposalNo.
*/
public void setProposalNo(ProposalNumber proposalNo) {
this.proposalNo = proposalNo;
}
/**
* Getter for property msgType.
* @return Value of property msgType.
*/
public MsgType getMsgType() {
return this.msgType;
}
/**
* Setter for property msgType.
* @param msgType New value of property msgType.
*/
/*public void setMsgType(MsgType msgType) {
this.msgType = msgType;
}*/
/**
* Getter for property leaseHolder.
* @return Value of property leaseHolder.
*/
public ASCIIString getLeaseHolder() {
return this.leaseHolder;
}
/**
* Setter for property leaseHolder.
* @param leaseHolder New value of property leaseHolder.
*/
public void setLeaseHolder(ASCIIString leaseHolder) {
this.leaseHolder = leaseHolder;
}
/**
* Getter for property leaseTimeout.
* @return Value of property leaseTimeout.
*/
public long getLeaseTimeout() {
return this.leaseTimeout;
}
/**
* Setter for property leaseTimeout.
* @param leaseTimeout New value of property leaseTimeout.
*/
public void setLeaseTimeout(long leaseTimeout) {
this.leaseTimeout = leaseTimeout;
}
/**
* Getter for property cellId.
* @return Value of property cellId.
*/
public ASCIIString getCellId() {
return this.cellId;
}
/**
* Setter for property cellId.
* @param cellId New value of property cellId.
*/
public void setCellId(ASCIIString cellId) {
this.cellId = cellId;
}
/**
* @return the sendTimestamp
*/
public long getSendTimestamp() {
return sendTimestamp;
}
/**
* @param sendTimestamp the sendTimestamp to set
*/
public void setSendTimestamp(long sendTimestamp) {
this.sendTimestamp = sendTimestamp;
}
/**
* @return the sender
*/
public InetSocketAddress getSender() {
return address;
}
/**
* @param sender the sender to set
*/
public void setSender(InetSocketAddress sender) {
this.address = sender;
}
/**
* checks if this message is before other
* @param other another message
* @return true if this message is before other
*/
public boolean before(FleaseMessage other) {
return proposalNo.before(other.proposalNo);
}
/**
* checks if this message is after other
* @param other another message
* @return true if this message is after (i.e. >) other
*/
public boolean after(FleaseMessage other) {
return proposalNo.after(other.proposalNo);
}
/**
* checks if both messages have the same message id.
* @param other another message
* @return true if both messages have the same message id
*/
public boolean sameMsgId(FleaseMessage other) {
return proposalNo.sameNumber(other.proposalNo);
}
/**
* toString
* @return a string representation of the message
*/
@Override
public String toString() {
assert(this.msgType != null);
return String.format("FleaseMessage ( type=%s cell=%s v=%d b=%s lease=%s/%d(%s) prevb=%s ts=%d(%s) addr=%s mepoch=%d)",
this.msgType.toString(),this.cellId,this.viewId,this.proposalNo,this.leaseHolder,
this.leaseTimeout,new Date(this.leaseTimeout),this.prevProposalNo,this.sendTimestamp,new Date(this.sendTimestamp),
(address != null) ? address.toString() : "n/a", this.masterEpochNumber);
}
public boolean isInternalEvent() {
return msgType == MsgType.EVENT_RESTART ||
msgType == MsgType.EVENT_TIMEOUT_ACCEPT ||
msgType == MsgType.EVENT_TIMEOUT_PREPARE;
}
public boolean isAcceptorMessage() {
return msgType == MsgType.MSG_ACCEPT ||
msgType == MsgType.MSG_LEARN ||
msgType == MsgType.MSG_PREPARE ||
msgType == MsgType.MSG_LEASE_RETURN;
}
public boolean isProposerMessage() {
return msgType == MsgType.MSG_ACCEPT_ACK ||
msgType == MsgType.MSG_ACCEPT_NACK ||
msgType == MsgType.MSG_PREPARE_ACK ||
msgType == MsgType.MSG_PREPARE_NACK;
}
public int getSize() {
return 1+cellId.getSerializedSize()+
(leaseHolder == null ? 4 : leaseHolder.getSerializedSize())+
8+8+8+8+8+8+4+8;
}
public void serialize(ReusableBuffer buffer) {
assert(buffer != null);
buffer.put((byte)this.msgType.ordinal());
cellId.marshall(buffer);
proposalNo.serialize(buffer);
prevProposalNo.serialize(buffer);
buffer.putLong(this.getSendTimestamp());
buffer.putLong(this.leaseTimeout);
if (leaseHolder != null)
this.leaseHolder.marshall(buffer);
else
buffer.putInt(0);
buffer.putInt(this.viewId);
buffer.putLong(this.masterEpochNumber);
}
public FleaseMessage(ReusableBuffer buffer) {
assert(buffer != null);
this.msgType = MsgType.values()[buffer.get()];
this.cellId = ASCIIString.unmarshall(buffer);
this.proposalNo = new ProposalNumber(buffer);
this.prevProposalNo = new ProposalNumber(buffer);
this.setSendTimestamp(buffer.getLong());
this.leaseTimeout = buffer.getLong();
this.leaseHolder = ASCIIString.unmarshall(buffer);
this.viewId = buffer.getInt();
this.masterEpochNumber = buffer.getLong();
}
public boolean hasTimedOut(FleaseConfig cfg, long currentGlobalTimeout) {
assert(this.leaseTimeout > 0);
assert(this.leaseHolder != null);
return (this.leaseTimeout+cfg.getDMax() < currentGlobalTimeout);
}
public boolean hasNotTimedOut(FleaseConfig cfg, long currentGlobalTimeout) {
assert(this.leaseTimeout > 0);
assert(this.leaseHolder != null);
return (this.leaseTimeout-cfg.getDMax() > currentGlobalTimeout);
}
@Override
public FleaseMessage clone() {
FleaseMessage myClone = new FleaseMessage(this);
myClone.address = this.address;
myClone.cellId = this.cellId;
myClone.leaseHolder = this.leaseHolder;
myClone.leaseTimeout = this.leaseTimeout;
myClone.prevProposalNo = this.prevProposalNo;
myClone.proposalNo = this.proposalNo;
myClone.sendTimestamp = this.sendTimestamp;
myClone.viewId = this.viewId;
myClone.masterEpochNumber = this.masterEpochNumber;
return myClone;
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
/**
*
* @author bjko
*/
public class ProposalNumber implements Cloneable {
private final long proposalNo;
private final long senderId;
public static final ProposalNumber EMPTY_PROPOSAL_NUMBER = new ProposalNumber(0, 0);
public ProposalNumber(long proposalNo, long senderId) {
this.proposalNo = proposalNo;
this.senderId = senderId;
}
public ProposalNumber(ReusableBuffer buffer) {
this.proposalNo = buffer.getLong();
this.senderId = buffer.getLong();
}
/**
* checks if this message is before other
* @param other another message
* @return true if this message is before other
*/
public boolean before(ProposalNumber other) {
if (this.proposalNo < other.proposalNo) {
return true;
} else if (this.proposalNo > other.proposalNo) {
return false;
} else {
return (this.senderId < other.senderId);
}
}
/**
* checks if this message is after other
* @param other another message
* @return true if this message is after (i.e. >) other
*/
public boolean after(ProposalNumber other) {
if (this.proposalNo > other.proposalNo) {
return true;
} else if (this.proposalNo < other.proposalNo) {
return false;
} else {
return (this.senderId > other.senderId);
}
}
public boolean sameNumber(ProposalNumber other) {
return (senderId == other.senderId)&& (proposalNo == other.proposalNo);
}
public boolean isEmpty() {
if (this == EMPTY_PROPOSAL_NUMBER)
return true;
return this.sameNumber(EMPTY_PROPOSAL_NUMBER);
}
public void serialize(ReusableBuffer buffer) {
buffer.putLong(this.proposalNo);
buffer.putLong(this.senderId);
}
/**
* @return the proposalNo
*/
public long getProposalNo() {
return proposalNo;
}
/**
* @return the senderId
*/
public long getSenderId() {
return senderId;
}
public String toString() {
return "("+proposalNo+";"+senderId+")";
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicBoolean;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.logging.Logging;
/**
*
* @author bjko
*/
public class EchoClient {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Logging.start(Logging.LEVEL_DEBUG);
TimeSync ts = TimeSync.initializeLocal(50);
try {
ts.waitForStartup();
TCPClient com = new TCPClient(3334,null, new NIOServer() {
public void onAccept(NIOConnection connection) {
onConnect(connection);
}
public void onConnect(NIOConnection connection) {
System.out.println("connected to "+connection.getEndpoint());
connection.read(BufferPool.allocate(1024));
connection.setContext(new AtomicBoolean(false));
}
public void onRead(NIOConnection connection, ReusableBuffer buffer) {
System.out.println("read from "+connection);
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String contents = new String(data);
BufferPool.free(buffer);
connection.read(BufferPool.allocate(1024));
System.out.println(">> "+contents);
}
public void onClose(NIOConnection connection) {
System.out.println("connection from "+connection.getEndpoint()+" closed ");
}
public void onWriteFailed(IOException exception, Object context) {
System.out.println("could not write, context: "+context);
}
public void onConnectFailed(InetSocketAddress endpoint, IOException exception, Object context) {
System.out.println("could not connect to: "+endpoint+", context: "+context);
}
});
com.start();
com.waitForStartup();
ReusableBuffer data = ReusableBuffer.wrap("Hello world!\n".getBytes());
com.write(new InetSocketAddress("localhost", 3333), data, "Yagg");
Thread.sleep(100);
data = ReusableBuffer.wrap("Hello world!\n".getBytes());
com.write(new InetSocketAddress("localhost", 3333), data, "Yagga");
Thread.sleep(30000);
data = ReusableBuffer.wrap("YaggaYagga!\n".getBytes());
com.write(new InetSocketAddress("localhost", 3333), data, null);
Thread.sleep(2000);
com.shutdown();
ts.close();
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.logging.Logging;
/**
*
* @author bjko
*/
public class EchoServer implements NIOServer {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
try {
Logging.start(Logging.LEVEL_DEBUG);
TimeSync.initializeLocal(50);
EchoServer s = new EchoServer();
TCPCommunicator srv = new TCPCommunicator(s, 3333, null);
srv.start();
srv.waitForStartup();
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
public EchoServer() {
}
public void onAccept(NIOConnection connection) {
//ignore
System.out.println("connected: "+connection);
connection.read(BufferPool.allocate(1024));
}
public void onConnect(NIOConnection connection) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void onRead(NIOConnection connection, ReusableBuffer buffer) {
boolean done = false;
System.out.println("do read: "+connection);
for (int i = 0; i < buffer.position(); i++) {
if (buffer.get(i) == '\n') {
done = true;
break;
}
}
if (done || !buffer.hasRemaining()) {
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String contents = new String(data);
if (contents.startsWith("quit")) {
try {
connection.close();
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
//we have a full line
System.out.println("new buffer: "+connection);
buffer.clear();
if (contents.startsWith("stats")) {
contents = BufferPool.getStatus();
} else {
contents = "you said: "+contents;
}
buffer.put(contents.getBytes());
buffer.flip();
connection.write(buffer,null);
connection.read(BufferPool.allocate(1024));
}
}
}
public void onClose(NIOConnection connection) {
System.out.println("disconnected: "+connection);
}
public void onWriteFailed(IOException exception, Object context) {
System.out.println("an error occurred: "+exception);
}
public void onConnectFailed(InetSocketAddress endpoint, IOException exception, Object context) {
//ignore
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.net.InetSocketAddress;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
/**
*
* @author bjko
*/
public class NIOConnection {
private TCPConnection connection;
private Object context;
public NIOConnection(TCPConnection connection) {
this.connection = connection;
}
public void setContext(Object context) {
this.context = context;
}
public Object getContext() {
return context;
}
/**
* READ MUST ONLY BE USED FROM A NIOServer callback!
* @param buffer
*/
public void read(ReusableBuffer buffer) {
connection.setReceiveBuffer(buffer);
}
/**
* Write is thread safe
* @param buffer
*/
public void write(ReusableBuffer buffer, Object context) {
connection.getServer().write(connection, buffer, context);
//FIXME:wakeup selector, change interest set
}
public void close() {
connection.getServer().closeConnection(connection);
}
public InetSocketAddress getEndpoint() {
return connection.getEndpoint();
}
public String toString() {
return "TCP connection (from "+connection.getChannel().socket().getRemoteSocketAddress()+" to local server @ "+connection.getServer().getPort()+")";
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
/**
*
* @author bjko
*/
public interface NIOServer {
/**
* called upon incoming connections.
* @param connection
*/
public void onAccept(NIOConnection connection);
/**
* called when a connection was established
* make sure to issue the first write
* @param connection
*/
public void onConnect(NIOConnection connection);
/**
* called when new data is available
* @param connection
* @param buffer
*/
public void onRead(NIOConnection connection, ReusableBuffer buffer);
/**
* called when a connection is closed
* @param connection
*/
public void onClose(NIOConnection connection);
public void onWriteFailed(IOException exception, Object context);
public void onConnectFailed(InetSocketAddress endpoint, IOException exception, Object context);
}

View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.xtreemfs.foundation.LifeCycleListener;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.logging.Logging;
/**
*
* @author bjko
*/
public class TCPClient {
private static final long MAX_WAITTIME_MS = 1000 * 60 * 10;
final Map<InetSocketAddress, ClientConnection> connections;
final ReadWriteLock conLock;
final TCPCommunicator server;
final NIOServer implementation;
final Timer closeTimer;
public TCPClient(int port, InetAddress bindAddr, final NIOServer implementation) throws IOException {
conLock = new ReentrantReadWriteLock();
connections = new HashMap();
this.implementation = implementation;
NIOServer impl = new NIOServer() {
public void onAccept(NIOConnection connection) {
final InetSocketAddress endpt = connection.getEndpoint();
try {
conLock.writeLock().lock();
ClientConnection cc = connections.get(endpt);
if (cc == null) {
cc = new ClientConnection();
cc.setConnection(connection);
cc.connectSucces();
connections.put(endpt,cc);
}
} finally {
conLock.writeLock().unlock();
}
implementation.onAccept(connection);
}
public void onConnect(NIOConnection connection) {
final InetSocketAddress endpt = connection.getEndpoint();
try {
conLock.writeLock().lock();
ClientConnection cc = connections.get(endpt);
if (cc != null)
cc.connectSucces();
else {
Logging.logMessage(Logging.LEVEL_ERROR, this,"connect for unknown connection: "+connection);
connection.close();
}
} finally {
conLock.writeLock().unlock();
}
implementation.onConnect(connection);
}
public void onRead(NIOConnection connection, ReusableBuffer buffer) {
implementation.onRead(connection, buffer);
}
public void onClose(NIOConnection connection) {
final InetSocketAddress endpt = connection.getEndpoint();
try {
conLock.writeLock().lock();
connections.remove(endpt);
} finally {
conLock.writeLock().unlock();
}
implementation.onClose(connection);
}
public void onWriteFailed(IOException exception, Object context) {
implementation.onWriteFailed(exception, context);
}
public void onConnectFailed(InetSocketAddress endpoint, IOException exception, Object context) {
System.out.println("connect failed for: "+endpoint);
try {
conLock.readLock().lock();
ClientConnection cc = connections.get(endpoint);
if (cc != null) {
synchronized (cc) {
cc.connectFailed();
cc.setConnection(null);
}
}
} finally {
conLock.readLock().unlock();
}
implementation.onConnectFailed(endpoint,exception,context);
}
};
server = new TCPCommunicator(impl, port, bindAddr);
closeTimer = new Timer();
/*closeTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
final long now = TimeSync.getLocalSystemTime();
try {
conLock.writeLock().lock();
for (Entry<InetSocketAddress,ClientConnection> e : connections.entrySet()) {
if (e.getValue().lastConnectAttempt_ms)
}
} finally {
conLock.writeLock().unlock();
}
}
}, CON_TIMEOUT, CON_TIMEOUT);
*/
}
public void write(InetSocketAddress remote, ReusableBuffer data, Object context) {
ClientConnection client = null;
try {
conLock.readLock().lock();
client = connections.get(remote);
} finally {
conLock.readLock().unlock();
}
if (client == null) {
try {
conLock.writeLock().lock();
client = connections.get(remote);
if (client == null) {
client = new ClientConnection();
connections.put(remote, client);
}
} finally {
conLock.writeLock().unlock();
}
}
synchronized (client) {
try {
if (!client.isConnected()) {
if (client.canReconnect()) {
NIOConnection con = server.connect(remote,null);
client.setConnection(con);
} else {
implementation.onWriteFailed(new IOException("cannot connect to server, blocked due to reconnect timeout"), context);
return;
}
}
} catch (IOException ex) {
implementation.onWriteFailed(ex, context);
return;
}
assert(client.getConnection() != null);
client.getConnection().write(data, context);
}
}
public void start() {
server.start();
}
public void waitForStartup() throws Exception {
server.waitForStartup();
}
public void shutdown() {
server.shutdown();
closeTimer.cancel();
}
public void waitForShutdown() throws Exception {
server.waitForShutdown();
}
public void setLifeCycleListener(LifeCycleListener l) {
server.setLifeCycleListener(l);
}
public int getSendQueueSize() {
return server.getSendQueueSize();
}
private static class ClientConnection {
NIOConnection connection;
long lastConnectAttempt_ms;
long waitTime_ms;
public ClientConnection() {
lastConnectAttempt_ms = 0;
waitTime_ms = 1000;
}
public NIOConnection getConnection() {
return connection;
}
public void setConnection(NIOConnection connection) {
this.connection = connection;
}
public boolean canReconnect() {
return (lastConnectAttempt_ms + waitTime_ms < TimeSync.getLocalSystemTime());
}
public boolean isConnected() {
return (connection != null);
}
public void connectSucces() {
waitTime_ms = 1000;
lastConnectAttempt_ms = 0;
}
public void connectFailed() {
lastConnectAttempt_ms = TimeSync.getLocalSystemTime();
waitTime_ms = waitTime_ms * 2;
if (waitTime_ms > MAX_WAITTIME_MS) {
waitTime_ms = MAX_WAITTIME_MS;
}
}
}
}

View File

@@ -0,0 +1,557 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import org.xtreemfs.foundation.LifeCycleThread;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.flease.comm.tcp.TCPConnection.SendRequest;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
*
* @author bjko
*/
public class TCPCommunicator extends LifeCycleThread {
private final int port;
/**
* the server socket
*/
private final ServerSocketChannel socket;
/**
* Selector for server socket
*/
private final Selector selector;
private final NIOServer implementation;
private final List<TCPConnection> connections;
private final Queue<TCPConnection> pendingCons;
private final AtomicInteger sendQueueSize;
/**
*
* @param implementation
* @param port, 0 to disable server mode
* @param bindAddr
* @throws IOException
*/
public TCPCommunicator(NIOServer implementation, int port, InetAddress bindAddr) throws IOException {
super("TCPcom@" + port);
this.port = port;
this.implementation = implementation;
this.connections = new LinkedList();
this.pendingCons = new ConcurrentLinkedQueue();
sendQueueSize = new AtomicInteger();
// open server socket
if (port == 0) {
socket = null;
} else {
socket = ServerSocketChannel.open();
socket.configureBlocking(false);
socket.socket().setReceiveBufferSize(256 * 1024);
socket.socket().setReuseAddress(true);
socket.socket().bind(
bindAddr == null ? new InetSocketAddress(port) : new InetSocketAddress(bindAddr, port));
}
// create a selector and register socket
selector = Selector.open();
if (socket != null)
socket.register(selector, SelectionKey.OP_ACCEPT);
}
/**
* Stop the server and close all connections.
*/
public void shutdown() {
this.interrupt();
}
/**
* sends a response.
*
* @param request
* the request
*/
public void write(TCPConnection connection, ReusableBuffer buffer, Object context) {
assert (buffer != null);
synchronized (connection) {
if (connection.getChannel().isConnected()) {
if (connection.sendQueueIsEmpty()) {
try {
int bytesWritten = connection.getChannel().write(buffer.getBuffer());
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, this,"directly wrote %d bytes to %s",bytesWritten,connection.getChannel().socket().getRemoteSocketAddress().toString());
}
if (bytesWritten < 0) {
if (context != null)
implementation.onWriteFailed(new IOException("remote party closed connection while writing"), context);
abortConnection(connection,new IOException("remote party closed connection while writing"));
return;
}
if (!buffer.hasRemaining()) {
//we are done
BufferPool.free(buffer);
return;
}
} catch (ClosedChannelException ex) {
if (context != null)
implementation.onWriteFailed(ex, context);
abortConnection(connection,ex);
} catch (IOException ex) {
if (Logging.isDebug())
Logging.logError(Logging.LEVEL_DEBUG, this,ex);
if (context != null)
implementation.onWriteFailed(ex, context);
abortConnection(connection,ex);
}
}
synchronized (connection) {
boolean isEmpty = connection.sendQueueIsEmpty();
if (isEmpty) {
try {
SelectionKey key = connection.getChannel().keyFor(selector);
if (key != null) {
key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
}
} catch (CancelledKeyException ex) {
}
}
}
sendQueueSize.incrementAndGet();
connection.addToSendQueue(new TCPConnection.SendRequest(buffer, context));
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, this,"enqueued write to %s",connection.getEndpoint());
}
selector.wakeup();
} else {
// ignore and free bufers
if (connection.getChannel().isConnectionPending()) {
sendQueueSize.incrementAndGet();
connection.addToSendQueue(new TCPConnection.SendRequest(buffer, context));
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, this,"enqueued write to %s",connection.getEndpoint());
}
} else {
BufferPool.free(buffer);
if (context != null)
implementation.onWriteFailed(new IOException("Connection already closed"), context);
}
}
}
}
public void run() {
notifyStarted();
if (Logging.isInfo()) {
Logging.logMessage(Logging.LEVEL_INFO, Category.net, this, "TCP Server @%d ready", port);
}
try {
while (!isInterrupted()) {
// try to select events...
try {
final int numKeys = selector.select();
if (!pendingCons.isEmpty()) {
while (true) {
TCPConnection con = pendingCons.poll();
if (con == null) {
break;
}
try {
assert(con.getChannel() != null);
con.getChannel().register(selector,
SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE | SelectionKey.OP_READ, con);
} catch (ClosedChannelException ex) {
abortConnection(con,ex);
}
}
}
if (numKeys == 0) {
continue;
}
} catch (CancelledKeyException ex) {
// who cares
} catch (IOException ex) {
Logging.logMessage(Logging.LEVEL_WARN, Category.net, this,
"Exception while selecting: %s", ex.toString());
continue;
}
// fetch events
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
// process all events
while (iter.hasNext()) {
SelectionKey key = iter.next();
// remove key from the list
iter.remove();
try {
if (key.isAcceptable()) {
acceptConnection(key);
}
if (key.isConnectable()) {
connectConnection(key);
}
if (key.isReadable()) {
readConnection(key);
}
if (key.isWritable()) {
writeConnection(key);
}
} catch (CancelledKeyException ex) {
// nobody cares...
continue;
}
}
}
for (TCPConnection con : connections) {
try {
con.close(implementation,new IOException("server shutdown"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
// close socket
selector.close();
if (socket != null)
socket.close();
if (Logging.isInfo()) {
Logging.logMessage(Logging.LEVEL_INFO, Category.net, this,
"TCP Server @%d shutdown complete", port);
}
notifyStopped();
} catch (Throwable thr) {
Logging.logMessage(Logging.LEVEL_ERROR, Category.net, this, "TPC Server @%d CRASHED!", port);
notifyCrashed(thr);
}
}
private void connectConnection(SelectionKey key) {
final TCPConnection con = (TCPConnection) key.attachment();
final SocketChannel channel = con.getChannel();
try {
if (channel.isConnectionPending()) {
channel.finishConnect();
}
synchronized (con) {
if (con.getSendBuffer() != null) {
key.interestOps(SelectionKey.OP_WRITE | SelectionKey.OP_READ);
} else {
key.interestOps(SelectionKey.OP_READ);
}
}
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "connected from %s to %s", con
.getChannel().socket().getLocalSocketAddress().toString(), channel.socket().getRemoteSocketAddress()
.toString());
}
implementation.onConnect(con.getNIOConnection());
} catch (IOException ex) {
if (Logging.isDebug()) {
Logging.logError(Logging.LEVEL_DEBUG, this,ex);
}
implementation.onConnectFailed(con.getEndpoint(), ex, con.getNIOConnection().getContext());
con.close(implementation,ex);
}
}
public NIOConnection connect(InetSocketAddress server, Object context) throws IOException {
TCPConnection con = openConnection(server,context);
return con.getNIOConnection();
}
private TCPConnection openConnection(InetSocketAddress server, Object context) throws IOException {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "connect to %s", server
.toString());
}
SocketChannel channel = null;
TCPConnection con = null;
try {
channel = SocketChannel.open();
channel.configureBlocking(false);
//channel.socket().setTcpNoDelay(true);
channel.socket().setReceiveBufferSize(256 * 1024);
channel.connect(server);
con = new TCPConnection(channel, this, server);
con.getNIOConnection().setContext(context);
pendingCons.add(con);
selector.wakeup();
if (Logging.isDebug())
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "connection established");
return con;
} catch (IOException ex) {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "cannot contact server %s",
server);
}
if (con != null)
con.close(implementation, ex);
throw ex;
}
}
/**
* accept a new incomming connection
*
* @param key
* the acceptable key
*/
private void acceptConnection(SelectionKey key) {
SocketChannel client = null;
TCPConnection connection = null;
// FIXME: Better exception handling!
try {
// accept connection
client = socket.accept();
connection = new TCPConnection(client,this,(InetSocketAddress)client.socket().getRemoteSocketAddress());
// and configure it to be non blocking
// IMPORTANT!
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ, connection);
//client.socket().setTcpNoDelay(true);
//numConnections.incrementAndGet();
connections.add(connection);
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "connect from client at %s",
client.socket().getRemoteSocketAddress().toString());
}
implementation.onAccept(connection.getNIOConnection());
} catch (ClosedChannelException ex) {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"cannot establish connection: %s", ex.toString());
}
} catch (IOException ex) {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"cannot establish connection: %s", ex.toString());
}
}
}
/**
* read data from a readable connection
*
* @param key
* a readable key
*/
private void readConnection(SelectionKey key) {
final TCPConnection con = (TCPConnection) key.attachment();
final SocketChannel channel = con.getChannel();
try {
while (true) {
final ReusableBuffer readBuf = con.getReceiveBuffer();
if (readBuf == null)
return;
final int numBytesRead = channel.read(readBuf.getBuffer());
if (numBytesRead == -1) {
// connection closed
if (Logging.isInfo()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"client closed connection (EOF): %s", channel.socket()
.getRemoteSocketAddress().toString());
}
abortConnection(con,new IOException("remote end closed connection while reading data"));
return;
} else if (numBytesRead == 0) {
return;
}
implementation.onRead(con.getNIOConnection(), readBuf);
}
} catch (ClosedChannelException ex) {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"connection to %s closed by remote peer", con.getChannel().socket()
.getRemoteSocketAddress().toString());
}
abortConnection(con,ex);
} catch (IOException ex) {
// simply close the connection
if (Logging.isDebug()) {
Logging.logError(Logging.LEVEL_DEBUG, this, ex);
}
abortConnection(con,ex);
}
}
/**
* write data to a writeable connection
*
* @param key
* the writable key
*/
private void writeConnection(SelectionKey key) {
final TCPConnection con = (TCPConnection) key.attachment();
final SocketChannel channel = con.getChannel();
SendRequest srq = null;
try {
while (true) {
srq = con.getSendBuffer();
if (srq == null) {
synchronized (con) {
srq = con.getSendBuffer();
if (srq == null) {
// no more responses, stop writing...
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
return;
}
}
}
// send data
final long numBytesWritten = channel.write(srq.getData().getBuffer());
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, this,"wrote %d bytes to %s",numBytesWritten,channel.socket().getRemoteSocketAddress().toString());
}
if (numBytesWritten == -1) {
if (Logging.isInfo()) {
Logging.logMessage(Logging.LEVEL_INFO, Category.net, this,
"client closed connection (EOF): %s", channel.socket().getRemoteSocketAddress().toString());
}
// connection closed
abortConnection(con, new IOException("remote end closed connection while writing data"));
return;
}
if (srq.getData().hasRemaining()) {
// not enough data...
break;
}
// finished sending fragment
// clean up :-) request finished
BufferPool.free(srq.getData());
sendQueueSize.decrementAndGet();
con.nextSendBuffer();
}
} catch (ClosedChannelException ex) {
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this,
"connection to %s closed by remote peer", con.getChannel().socket().getRemoteSocketAddress().toString());
}
abortConnection(con,ex);
} catch (IOException ex) {
// simply close the connection
if (Logging.isDebug()) {
Logging.logError(Logging.LEVEL_DEBUG, this, ex);
}
abortConnection(con,ex);
}
}
public int getSendQueueSize() {
return sendQueueSize.get();
}
void closeConnection(TCPConnection con) {
if (con.isClosed())
return;
con.setClosed();
final SocketChannel channel = con.getChannel();
// remove the connection from the selector and close socket
try {
synchronized (connections) {
connections.remove(con);
}
final SelectionKey key = channel.keyFor(selector);
if (key != null)
key.cancel();
con.close(null,null);
} catch (Exception ex) {
}
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "closing connection to %s", channel
.socket().getRemoteSocketAddress().toString());
}
}
void abortConnection(TCPConnection con, IOException exception) {
if (con.isClosed())
return;
con.setClosed();
final SocketChannel channel = con.getChannel();
// remove the connection from the selector and close socket
try {
synchronized (connections) {
connections.remove(con);
}
final SelectionKey key = channel.keyFor(selector);
if (key != null)
key.cancel();
con.close(implementation,exception);
} catch (Exception ex) {
}
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.net, this, "closing connection to %s", channel
.socket().getRemoteSocketAddress().toString());
}
implementation.onClose(con.getNIOConnection());
}
int getPort() {
return this.port;
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
/**
*
* @author bjko
*/
public class TCPConnection {
private SocketChannel channel;
private Queue<SendRequest> sendQueue;
private ReusableBuffer receiveBuffer;
private final NIOConnection nioCon;
private final TCPCommunicator myServer;
private final AtomicBoolean closed;
private final InetSocketAddress endpoint;
public TCPConnection(SocketChannel channel, TCPCommunicator myServer, InetSocketAddress endpoint) {
this.channel = channel;
sendQueue = new ConcurrentLinkedQueue<SendRequest>();
nioCon = new NIOConnection(this);
this.myServer = myServer;
closed = new AtomicBoolean(false);
this.endpoint = endpoint;
}
public TCPCommunicator getServer() {
return myServer;
}
public NIOConnection getNIOConnection() {
return nioCon;
}
public SocketChannel getChannel() {
return channel;
}
public InetSocketAddress getEndpoint() {
return this.endpoint;
}
public SendRequest getSendBuffer() {
return sendQueue.peek();
}
public void nextSendBuffer() {
sendQueue.poll();
}
public void addToSendQueue(SendRequest buffer) {
sendQueue.add(buffer);
}
public boolean sendQueueIsEmpty() {
return sendQueue.isEmpty();
}
public ReusableBuffer getReceiveBuffer() {
return receiveBuffer;
}
public void setReceiveBuffer(ReusableBuffer buffer) {
receiveBuffer = buffer;
}
public boolean isClosed() {
return closed.get();
}
public void setClosed() {
closed.set(true);
}
public void close(NIOServer implementation, IOException error) {
try {
BufferPool.free(receiveBuffer);
channel.close();
} catch (IOException ex) {
//ignore
} finally {
for (SendRequest rq : sendQueue) {
BufferPool.free(rq.data);
}
if (implementation != null) {
for (SendRequest rq : sendQueue) {
if (rq.getContext() != null)
implementation.onWriteFailed(error, rq.getContext());
}
}
}
}
public static class SendRequest {
private final ReusableBuffer data;
private final Object context;
public SendRequest(ReusableBuffer data, Object context) {
this.data = data;
this.context = context;
}
/**
* @return the data
*/
public ReusableBuffer getData() {
return data;
}
/**
* @return the context
*/
public Object getContext() {
return context;
}
}
}

View File

@@ -0,0 +1,234 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm.tcp;
import org.xtreemfs.foundation.flease.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteOrder;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.xtreemfs.foundation.LifeCycleListener;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.logging.Logging;
/**
*
* @author bjko
*/
public class TCPFleaseCommunicator implements FleaseMessageSenderInterface {
private final FleaseStage stage;
private final int port;
private TCPClient comm;
private volatile boolean quit;
private final AtomicBoolean sendMode;
private final LinkedBlockingQueue<FleaseMessage> q;
private static final int MAX_UDP_SIZE = 16*1024;
private long numTx,numRx;
public static TCPFleaseCommunicator instance;
private AtomicInteger numIn, numOut;
public TCPFleaseCommunicator(FleaseConfig config, String lockfileDir,
boolean ignoreLockForTesting,
final FleaseViewChangeListenerInterface viewListener, FleaseStatusListener fsl, MasterEpochHandlerInterface meHandler) throws Exception {
stage = new FleaseStage(config, lockfileDir, this, ignoreLockForTesting, viewListener,fsl,meHandler);
port = config.getEndpoint().getPort();
q = new LinkedBlockingQueue<FleaseMessage>();
sendMode = new AtomicBoolean(false);
numTx = 0;
numRx = 0;
numIn = new AtomicInteger();
numOut = new AtomicInteger();
instance = this; //only for testing!
comm = new TCPClient(port, null, new NIOServer() {
public void onAccept(NIOConnection connection) {
ReusableBuffer hdr = BufferPool.allocate(4);
hdr.getBuffer().order(ByteOrder.LITTLE_ENDIAN);
ReusableBuffer bdy = BufferPool.allocate(2048);
bdy.getBuffer().order(ByteOrder.LITTLE_ENDIAN);
Connection c = new Connection(hdr, bdy);
connection.setContext(c);
connection.read(hdr);
}
public void onConnect(NIOConnection connection) {
onAccept(connection);
}
public void onRead(NIOConnection connection, ReusableBuffer buffer) {
Connection c = (Connection) connection.getContext();
try {
if (c.readingHdr) {
if (buffer.hasRemaining()) {
connection.read(buffer);
} else {
buffer.flip();
c.readingHdr = false;
int size = buffer.getInt();
if ((size <= 0) || (size > 2048)) {
Logging.logMessage(Logging.LEVEL_ERROR, this,"warining: invalid fragment size: %d",size);
connection.close();
return;
}
buffer.clear();
c.data.limit(size);
connection.read(c.data);
}
} else {
if (buffer.hasRemaining()) {
connection.read(buffer);
} else {
buffer.flip();
FleaseMessage m = new FleaseMessage(buffer);
m.setSender(connection.getEndpoint());
buffer.clear();
c.readingHdr = true;
connection.read(c.header);
stage.receiveMessage(m);
}
}
} catch (Exception ex) {
Logging.logError(Logging.LEVEL_ERROR, this,ex);
Logging.logMessage(Logging.LEVEL_ERROR, this,buffer.toString());
connection.close();
}
}
public void onClose(NIOConnection connection) {
Connection c = (Connection) connection.getContext();
if (c.readingHdr)
BufferPool.free(c.data);
else
BufferPool.free(c.header);
}
public void onWriteFailed(IOException exception, Object context) {
Logging.logMessage(Logging.LEVEL_ERROR, this,"write failed: "+context);
}
public void onConnectFailed(InetSocketAddress endpoint, IOException exception, Object context) {
Logging.logMessage(Logging.LEVEL_ERROR, this,"could not connect to: "+endpoint);
}
});
/*Timer t = new Timer(true);
t.scheduleAtFixedRate(new TimerTask() {
long maxQsize = 0;
long sum = 0;
long numSamples = 0;
int cnt = 0;
@Override
public void run() {
long size = comm.getSendQueueSize();
sum = sum+size;
numSamples++;
if (size > maxQsize)
maxQsize = size;
cnt++;
if (cnt == 10) {
System.out.println("avg: "+(sum/numSamples)+" max: "+maxQsize);
cnt = 0;
}
}
}, 10, 1000);*/
}
public FleaseStage getStage() {
return stage;
}
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
FleaseMessage m = message.clone();
m.setSender(recipient);
send(m);
if (FleaseStage.COLLECT_STATISTICS)
numOut.incrementAndGet();
}
/**
* sends a UDPRequest.
*
* @attention Overwrites the first byte of rq.data with the message type.
*/
public void send(FleaseMessage rq) {
if (FleaseStage.COLLECT_STATISTICS)
numIn.incrementAndGet();
final int size = rq.getSize();
ReusableBuffer data = BufferPool.allocate(size+4);
data.getBuffer().order(ByteOrder.LITTLE_ENDIAN);
data.putInt(size);
rq.serialize(data);
data.getBuffer().order(ByteOrder.BIG_ENDIAN);
data.flip();
if (data.remaining() != size+4)
throw new IllegalStateException("data is wrong: "+data);
comm.write(rq.getSender(), data, null);
}
public void start() throws Exception {
comm.start();
comm.waitForStartup();
stage.start();
stage.waitForStartup();
}
public void shutdown() throws Exception {
stage.shutdown();
stage.waitForShutdown();
comm.shutdown();
comm.waitForShutdown();
}
public void setLifeCycleListener(LifeCycleListener l) {
comm.setLifeCycleListener(l);
stage.setLifeCycleListener(l);
}
public int getNumIn() {
return numIn.getAndSet(0);
}
public int getNumOut() {
return numOut.getAndSet(0);
}
private static class Connection {
public ReusableBuffer header;
public ReusableBuffer data;
public boolean readingHdr;
public Connection(ReusableBuffer header, ReusableBuffer data) {
this.header = header;
this.data = data;
readingHdr = true;
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2012 by Bjoern Kolbeck.
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.proposer;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Stores a single action for traces.
* @author bjko
*/
public class CellAction {
private final ActionName actionName;
private final String message;
public static enum ActionName {
PROPOSER_SET_VIEWID,
PROPOSER_CELL_OPENED,
PROPOSER_CELL_CLOSED,
PROPOSER_ACQUIRE_LEASE,
PROPOSER_RETURNED_LOCAL_LEASE,
PROPOSER_START_RENEW,
PROPOSER_RENEW_CANCELLED,
PROPOSER_RENEW_FAILED_NO_LEASE,
PROPOSER_RENEW_FAILED_LEASE_TO,
PROPOSER_RENEW_FAILED_LEASE_NOT_ENOUGH_TIME,
PROPOSER_RENEW_FAILED_NOT_OWNER,
PROPOSER_HANDOVER_LEASE,
PROPOSER_RESTART_EVENT,
PROPOSER_RENEW_EVENT,
PROPOSER_INTERNAL_ERROR_CELL_RESET,
PROPOSER_SET_BALLOT_NO,
PROPOSER_REQUEST_MASTER_EPOCH,
PROPOSER_WAIT_FOR_ACK,
PROPOSER_PREPARE_START,
PROPOSER_PREPARE_PROCESS_RESPONSE,
PROPOSER_PREPARE_TIMEOUT,
PROPOSER_VIEW_OUTDATED,
PROPOSER_PREPARE_OVERRULED,
PROPOSER_PREPARE_SUCCESS,
PROPOSER_PREPARE_EMPTY,
PROPOSER_PREPARE_PRIOR_VALUE,
PROPOSER_PREPARE_IMPLICIT_RENEW,
PROPOSER_PREPARE_MAX_MASTER_EPOCH,
PROPOSER_ACCEPT_START,
PROPOSER_ACCEPT_PROCESS_RESPONSE,
PROPOSER_ACCEPT_TIMEOUT,
PROPOSER_ACCEPT_OVERRULED,
PROPOSER_LEARN_START,
PROPOSER_LEARN_TIMED_OUT,
PROPOSER_SCHEDULED_RENEW,
PROPOSER_LEARN_LEASE_IN_GRACE_PERIOD,
PROPOSER_CANCELLED,
PROPOSER_CANCEL_LEASE_FAILED,
PROPOSER_CANCEL_SCHEDULE_RESTART,
PROPOSER_RECEIVED_OUT_OF_SYNC_MSG,
PROPOSER_RENEW_LEASE,
PROPOSER_RENEW_FAILED_NO_LOCAL_LEASE_INFO,
PROPOSER_SCHEDULED_RESTART,
PROPOSER_SCHEDULED_TIMEOUT,
PROPOSER_PREPARE_FAILED,
PROPOSER_PREPARE_LEASE_TO,
PROPOSER_ACCEPT_FAILED,
PROPOSER_ACCEPT_SUCCESS,
}
public static class CellActionList implements Iterable<CellAction> {
public static final int MAX_ACTIONS_IN_LIST = 50;
List<CellAction> actions;
public CellActionList() {
actions = new LinkedList<CellAction>();
}
public void addAction(ActionName actionName) {
addAction(actionName, null);
}
public void addAction(ActionName actionName, String message) {
actions.add(new CellAction(actionName, message));
if (actions.size() > MAX_ACTIONS_IN_LIST) {
actions.remove(0);
}
}
@Override
public Iterator<CellAction> iterator() {
return actions.iterator();
}
@Override
public String toString() {
StringBuilder text = new StringBuilder();
text.append("actions:[");
Iterator<CellAction> iter = iterator();
while (iter.hasNext()) {
CellAction action = iter.next();
text.append(action);
if (iter.hasNext()) {
text.append(", ");
}
}
text.append("]");
return text.toString();
}
}
public CellAction(ActionName actionName) {
this.actionName = actionName;
this.message = null;
}
public CellAction(ActionName actionName, String message) {
this.actionName = actionName;
this.message = message;
}
public String toString() {
return actionName + (message != null
? " (" + message +")"
: "");
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.proposer;
/**
*
* @author bjko
*/
public class FleaseException extends Exception {
private String fleaseCellDebugString = null;
public FleaseException(String message) {
super(message);
}
public FleaseException(String message, Throwable cause) {
super(message, cause);
}
public void addFleaseCellDebugString(String fleaseCellDebugString) {
this.fleaseCellDebugString = fleaseCellDebugString;
}
public String getFleaseCellDebugString() {
return fleaseCellDebugString;
}
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.proposer;
import org.xtreemfs.foundation.buffer.ASCIIString;
/**
*
* @author bjko
*/
public interface FleaseListener {
public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long masterEpochNumber);
public void proposalFailed(ASCIIString cellId, Throwable cause);
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.proposer;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
/**
*
* @author bjko
*/
public interface FleaseLocalQueueInterface {
public void enqueueMessage(FleaseMessage message);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,331 @@
/*
* Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.proposer;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.Flease;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.comm.ProposalNumber;
import org.xtreemfs.foundation.flease.proposer.CellAction.ActionName;
import org.xtreemfs.foundation.flease.proposer.CellAction.CellActionList;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
*
* @author bjko
*/
public class FleaseProposerCell {
/**
* @return the responses
*/
public List<FleaseMessage> getResponses() {
return responses;
}
/**
* @return the messageSent
*/
public FleaseMessage getMessageSent() {
return messageSent;
}
/**
* @param messageSent the messageSent to set
*/
public void setMessageSent(FleaseMessage messageSent) {
this.messageSent = messageSent;
}
/**
* @return the lastPrepateTimestamp_ms
*/
public long getLastPrepareTimestamp_ms() {
return lastPrepateTimestamp_ms;
}
public void setViewId(int viewId) {
this.viewId = viewId;
}
public int getViewId() {
return this.viewId;
}
public boolean isHandoverInProgress() {
return handoverTo != null;
}
/**
* @return the prevLease
*/
public Flease getPrevLease() {
return prevLease;
}
/**
* @param prevLease the prevLease to set
*/
public void setPrevLease(Flease prevLease) {
this.prevLease = prevLease;
}
/**
* @return the markedClose
*/
public boolean isMarkedClose() {
return markedClose;
}
/**
* @param markedClose the markedClose to set
*/
public void setMarkedClose(boolean markedClose) {
this.markedClose = markedClose;
}
/**
* @return the requestMasteEpoch
*/
public boolean isRequestMasteEpoch() {
return requestMasteEpoch;
}
/**
* @param requestMasteEpoch the requestMasteEpoch to set
*/
public void setRequestMasteEpoch(boolean requestMasteEpoch) {
this.requestMasteEpoch = requestMasteEpoch;
}
/**
* @return the masterEpochNumber
*/
public long getMasterEpochNumber() {
return masterEpochNumber;
}
/**
* @param masterEpochNumber the masterEpochNumber to set
*/
public void setMasterEpochNumber(long masterEpochNumber) {
this.masterEpochNumber = masterEpochNumber;
}
public static enum State {
IDLE,
WAIT_FOR_PREP_ACK,
WAIT_FOR_ACCEPT_ACK,
};
private final ASCIIString cellId;
private ProposalNumber ballotNo;
private List<InetSocketAddress> acceptors;
private final List<FleaseListener> listeners;
private final List<FleaseMessage> responses;
private State cellState;
private int numFailures;
private final int majority;
private long lastPrepateTimestamp_ms;
private int viewId;
private Flease prevLease;
private boolean markedClose;
private ASCIIString handoverTo;
private boolean requestMasteEpoch;
private long masterEpochNumber;
private final CellActionList actions;
/**
* the value to use for prepare, accept and learn
* might be != than the local host, if the proposer
* must use a previously accepted value
*/
private FleaseMessage messageSent;
FleaseProposerCell(ASCIIString cellId, List<InetSocketAddress> acceptors, long senderId) {
this.actions = new CellActionList();
this.cellId = cellId;
this.acceptors = acceptors;
this.responses = new ArrayList(acceptors.size()+1);
this.listeners = new ArrayList(5);
this.ballotNo = new ProposalNumber(TimeSync.getGlobalTime(),senderId);
this.majority = (int) Math.floor((acceptors.size()+1.0)/ 2.0) + 1;
this.prevLease = Flease.EMPTY_LEASE;
this.markedClose = false;
this.handoverTo = null;
if (Logging.isDebug()) {
Logging.logMessage(Logging.LEVEL_DEBUG, Category.replication, this,"opened new cell id %s with majority = %d ",cellId,majority);
}
}
public void addAction(ActionName actionName) {
actions.addAction(actionName);
}
public void addAction(ActionName actionName, String message) {
actions.addAction(actionName, message);
}
public boolean majorityAvail() {
return responses.size() >= this.majority;
}
/**
* @return the cellId
*/
public ASCIIString getCellId() {
return cellId;
}
/**
* @return the ballotNo
*/
public ProposalNumber getBallotNo() {
return ballotNo;
}
/**
* @param ballotNo the ballotNo to set
*/
public void setBallotNo(ProposalNumber ballotNo) {
this.ballotNo = ballotNo;
}
/**
* @return the acceptors
*/
public List<InetSocketAddress> getAcceptors() {
return acceptors;
}
/**
* @param acceptors the acceptors to set
*/
public void setAcceptors(List<InetSocketAddress> acceptors) {
this.acceptors = acceptors;
}
/**
* @return the cellState
*/
public State getCellState() {
return cellState;
}
/**
* @param cellState the cellState to set
*/
public void setCellState(State cellState) {
this.cellState = cellState;
}
/**
* @return the listeners
*/
public List<FleaseListener> getListeners() {
return listeners;
}
public int getNumAcceptors() {
return acceptors.size();
}
/**
* @return the numFailures
*/
public int getNumFailures() {
return numFailures;
}
/**
* @param numFailures the numFailures to set
*/
public void setNumFailures(int numFailures) {
this.numFailures = numFailures;
}
public void touch() {
this.lastPrepateTimestamp_ms = TimeSync.getLocalSystemTime();
}
/**
* @return the handoverTo
*/
public ASCIIString getHandoverTo() {
return handoverTo;
}
/**
* @param handoverTo the handoverTo to set
*/
public void setHandoverTo(ASCIIString handoverTo) {
this.handoverTo = handoverTo;
}
@Override
public String toString() {
StringBuilder text = new StringBuilder();
text.append(getClass().getSimpleName());
text.append(":{");
text.append(" cellId:");
text.append(cellId);
text.append(" ballotNo:");
text.append(ballotNo);
text.append(" numAcceptors:");
text.append(acceptors != null ? acceptors.size() : "null");
text.append(" numResponses:");
text.append(responses != null ? responses.size() : "null");
text.append(" cellState:");
text.append(cellState);
text.append(" numFail:");
text.append(numFailures);
text.append(" majority:");
text.append(majority);
text.append(" lastPTSP:");
text.append(lastPrepateTimestamp_ms);
text.append(" viewId:");
text.append(viewId);
text.append(" prevL:");
text.append(prevLease != null ? prevLease : "none");
text.append(" markedClose:");
text.append(markedClose);
text.append(" rqME:");
text.append(requestMasteEpoch);
text.append(" msgSent:");
text.append(messageSent);
text.append(" responses:");
for (FleaseMessage r : responses) {
text.append(r);
text.append(",");
}
text.append(" actions:");
text.append(actions);
text.append("}");
return text.toString();
}
}

View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.sim;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import org.xtreemfs.foundation.LifeCycleThread;
import org.xtreemfs.foundation.flease.FleaseStage;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.logging.Logging;
/**
* A tool to simulate package loss, temporary host disconnects and message delay.
* @author bjko
*/
public class Communicator extends LifeCycleThread {
/**
* the connected UDPSimSockets
*/
protected final Map<Integer,FleaseStage> ports;
/**
* sockets which are currently blocked (i.e. simulated network outage)
*/
protected final Map<Integer,Integer> blockedPorts;
/**
* the packet loss in percent (0..100)
*/
private int pkgLossPct;
/**
* if true the thread will quit operation
*/
private boolean quit;
/**
* debug output is generated if set to true
*/
private boolean debug;
/**
* queue with packets to be delivered to sockets
*/
private final LinkedBlockingQueue<Packet> sendQ;
/**
* singleton
*/
private static volatile Communicator theInstance;
/**
* thread for delayed delivery and blocking ports
*/
private DelayedDelivery dd;
private int minDelay;
private int maxDelay;
/**
* percent of packets to be delayed
*/
private int pctDelay;
/**
* if set to true, ports are blocked unsymmetric (i.e. receive but cannot send)
*/
private boolean halfLink;
/**
* Creates a new instance of UDPSim
* @param pkgLossPct packet loss in percent
* @param minDelay minimum delay of a delayed packet
* @param maxDelay maximum delay of a delayed packet
* @param pctDelay percentage of packets to be delayed
* @param halfLink if set to true, ports are blocked unsymmetric (i.e. receive but cannot send)
* @param pHostUnavail probability (0..1) that a host becomes unavailable
* @param pHostRecovery probability that a host is recovered. This value is multiplied by the
* number of rounds that the host is already unavailable.
* @param debug if set to true extensive debug output is generated
*/
public Communicator(int pkgLossPct, int minDelay, int maxDelay, int pctDelay,
boolean halfLink, double pHostUnavail, double pHostRecovery,
boolean debug) {
super("UDP-Sim");
this.ports = new ConcurrentHashMap();
this.blockedPorts = new ConcurrentHashMap();
this.pkgLossPct = pkgLossPct;
this.quit = false;
this.debug = debug;
this.sendQ = new LinkedBlockingQueue();
this.dd = new DelayedDelivery(sendQ,blockedPorts,ports,
pHostUnavail,pHostRecovery,
debug);
dd.start();
this.minDelay = minDelay;
this.maxDelay = maxDelay;
this.pctDelay = pctDelay;
this.halfLink = halfLink;
theInstance = this;
}
/**
* opens a port and delivers messages into the queue
* @param port port number to open
* @param q the queue to receive messages
* @return true if the port was opened succesfully, false if the port is already in use
*/
public boolean openPort(int port, FleaseStage stage) {
if (ports.get(port) != null)
return false;
ports.put(port,stage);
return true;
}
/**
* Opens a free port
* @param q the queue to receive messages
* @return treu if successful, false if there is no free port available
*/
public int openPort(FleaseStage stage) {
int tries = 0;
while (tries < 5) {
int rport = (int)(Math.random()*65000.0)+1;
if (ports.get(rport) == null) {
ports.put(rport,stage);
return rport;
}
tries++;
}
return -1;
}
/**
* closes the port
* @param port port number to close
*/
public void closePort(int port) {
ports.remove(port);
}
/**
* sends a datagram packet from
* @param port sending port number
* @param dp packet to send
*/
public synchronized void send(int port, FleaseMessage msg) {
Packet p = new Packet(msg,port);
sendQ.add(p);
}
/**
* main loop
*/
public void run() {
try {
InetAddress ia = InetAddress.getLocalHost();
notifyStarted();
while (!quit) {
try {
Packet p = sendQ.take();
FleaseStage rec = ports.get(p.recipientPort);
if (rec == null)
continue;
if (blockedPorts.containsKey(p.msg.getSender().getPort())) {
if (debug)
Logging.logMessage(Logging.LEVEL_DEBUG,this,"msg dropped, port blocked "+p.msg.getSender().getPort());
continue;
}
if (blockedPorts.containsKey(p.recipientPort)) {
if (debug)
Logging.logMessage(Logging.LEVEL_DEBUG,this,"msg dropped, port blocked "+p.recipientPort);
continue;
}
if (!dropPacket() || p.requeued) {
int delay = delayPacket();
if ((delay > 0) && !p.requeued) {
if (debug)
Logging.logMessage(Logging.LEVEL_DEBUG,this,"msg delayed "+delay+"ms "+p.recipientPort+" -> "+p.msg.getSender().getPort());
dd.add(p,delay);
} else {
//p.msg.setSender(new InetSocketAddress(ia, p.recipientPort));
try {
rec.receiveMessage(p.msg);
} catch (IllegalStateException e) {
//just drop it
}
}
} else {
if (debug)
Logging.logMessage(Logging.LEVEL_DEBUG,this,"msg lost "+p.recipientPort+" -> "+p.msg.getSender().getPort());
}
} catch (InterruptedException ex) {
Logging.logError(Logging.LEVEL_ERROR,this,ex);
}
}
} catch (UnknownHostException ex) {
Logging.logError(Logging.LEVEL_ERROR,this,ex);
}
notifyStopped();
}
/**
* decides if a message should be dropped.
* @return true, if the packet is to be dropped
*/
private boolean dropPacket() {
int rv = (int)(Math.random()*100.0);
return (rv < this.pkgLossPct);
}
/**
* singleton
* @return null, if not initialized, the instance otherwise
*/
public static Communicator getInstance() {
return theInstance;
}
/**
* kills the thread and the delayed delivery thread
*/
public void shutdown() {
try {
this.quit = true;
this.interrupt();
dd.shutdown();
dd.waitForShutdown();
waitForShutdown();
} catch (Exception exc) {
Logging.logError(Logging.LEVEL_ERROR, this, exc);
}
}
/**
* decides if and how long a packet is delayed
* @return delay in ms
*/
private int delayPacket() {
if (pctDelay == 0)
return 0;
int rv = (int)(Math.random()*100.0);
if (rv < this.pctDelay) {
return (int)(Math.random()*((double)maxDelay-minDelay))+minDelay;
} else {
return 0;
}
}
/**
* Packet information
*/
protected static class Packet {
/**
* the datagram that is being sent
*/
public FleaseMessage msg;
/**
* originating prot number
*/
public int recipientPort;
/**
* set to true if it was requeued after delay (i.e. must not be dropped, delayed...)
*/
public boolean requeued;
/**
* creates a new packet
* @param dp datagram packet
* @param port originating port
*/
public Packet(FleaseMessage msg, int port) {
this.msg = msg;
this.recipientPort = port;
this.requeued = false;
}
}
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.sim;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import org.xtreemfs.foundation.LifeCycleThread;
import org.xtreemfs.foundation.flease.FleaseStage;
import org.xtreemfs.foundation.logging.Logging;
/**
* Thread to deliver delayed packets and to set availability status of hosts.
* @author bjko
*/
public class DelayedDelivery extends LifeCycleThread {
/**
* queued packets for delayed delivery
*/
private final LinkedList<DelayPacket> packets;
/**
* sending queue
*/
private final LinkedBlockingQueue<Communicator.Packet> targetQ;
/**
* minimum delay in ms
*/
private int minDelay;
/**
* maximum delay in ms
*/
private int maxDelay;
/**
* if set to true the thread shuts down
*/
private boolean quit;
/**
* time to wait between two invocations in ms
*/
private static final int WAIT_TIME = 50;
/**
* list of blocked ports (unavailable hosts)
*/
private final Map<Integer,Integer> blockedPorts;
/**
* all ports
*/
private final Map<Integer,FleaseStage> ports;
/**
* probability of unavailable host
*/
private double pHostUnavail;
/**
* probability of host recovery
*/
private double pHostRecovery;
/**
* number of rounds (i.e. WAIT_TIME) to wait between checks for host availability
*/
private final static int HOSTWAIT_MULTIPLIER = 10;
/**
* if set to true debug output is generated
*/
private boolean debug;
/**
* Creates a new instance of UDPDelayedDelivery
* @param targetQ queue to use for delivering delayed packets
* @param blockedPorts list of blocked ports (unavail hosts)
* @param ports list of all hosts
* @param pHostUnavail probability of unavailable host
* @param pHostRecovery probability of host recovery
* @param debug if set to true debug output is generated
*/
public DelayedDelivery(LinkedBlockingQueue<Communicator.Packet> targetQ,
Map<Integer,Integer> blockedPorts,
Map<Integer,FleaseStage> ports,
double pHostUnavail, double pHostRecovery, boolean debug) {
super("UDP-Delivery");
this.packets = new LinkedList();
this.targetQ = targetQ;
/*this.minDelay = minDelay;
this.maxDelay = maxDelay;*/
this.pHostUnavail = pHostUnavail;
this.pHostRecovery = pHostRecovery;
this.blockedPorts = blockedPorts;
this.ports = ports;
this.quit = false;
this.debug = debug;
}
/**
* adds a packet for delyed delivery
* @param p packet to send
* @param delay delay in ms
*/
public void add(Communicator.Packet p, int delay) {
synchronized (packets) {
DelayPacket dp = new DelayPacket();
dp.packet = p;
dp.waited = 0;
dp.delay = delay;
packets.add(dp);
}
}
/**
* main loop
*/
public void run() {
notifyStarted();
int hostwait = 0;
while (!quit) {
synchronized (packets) {
Iterator<DelayPacket> iter = packets.iterator();
while (iter.hasNext()) {
DelayPacket dp = iter.next();
try {
dp.waited += WAIT_TIME;
if (dp.waited >= dp.delay) {
dp.packet.requeued = true;
iter.remove();
targetQ.add(dp.packet);
}
} catch (IllegalStateException ex) {
}
}
}
//check only every 10*WAIT_TIME
hostwait++;
if (hostwait == HOSTWAIT_MULTIPLIER) {
//check if hosts should become available again...
Iterator<Integer> iter = blockedPorts.keySet().iterator();
while (iter.hasNext()) {
int portNo = iter.next();
int round = blockedPorts.get(portNo);
if (Math.random() < this.pHostRecovery*round) {
iter.remove();
if (debug)
Logging.logMessage(Logging.LEVEL_DEBUG,this,"unblocked "+portNo);
} else {
blockedPorts.put(portNo,round+1);
}
}
//make hosts unavailable
if (blockedPorts.size() < ports.size()) {
if (Math.random() < this.pHostUnavail) {
//get a random host to make unavailable
Integer[] keys = ports.keySet().toArray(new Integer[0]);
int rand = (int)(Math.random()*(double)(keys.length));
blockedPorts.put(keys[rand],1);
if (debug)
Logging.logMessage(Logging.LEVEL_DEBUG,this,"blocked "+keys[rand]);
}
}
hostwait = 0;
}
synchronized (this) {
try {
this.wait(WAIT_TIME);
} catch (InterruptedException ex) {
}
}
}
notifyStopped();
}
/**
* shuts down the thread
*/
public void shutdown() {
this.quit = true;
this.interrupt();
}
/**
* information on packet to be delayed
*/
protected static class DelayPacket {
/**
* packet to send
*/
Communicator.Packet packet;
int delay;
/**
* time already waited
*/
int waited;
}
}

View File

@@ -0,0 +1,231 @@
///*
// * Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
// *
// * Licensed under the BSD License, see LICENSE file for details.
// *
// */
//
//package org.xtreemfs.foundation.flease.sim;
//
//import java.net.InetSocketAddress;
//import java.util.ArrayList;
//import java.util.Iterator;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.Semaphore;
//import java.util.concurrent.TimeUnit;
//import org.xtreemfs.common.TimeSync;
//import org.xtreemfs.common.buffer.ASCIIString;
//import org.xtreemfs.common.logging.Logging;
//import org.xtreemfs.common.logging.Logging.Category;
//import org.xtreemfs.foundation.LifeCycleListener;
//import org.xtreemfs.foundation.flease.FleaseConfig;
//import org.xtreemfs.foundation.flease.FleaseMessageSenderInterface;
//import org.xtreemfs.foundation.flease.FleaseStage;
//import org.xtreemfs.foundation.flease.FleaseViewChangeListenerInterface;
//import org.xtreemfs.foundation.flease.comm.FleaseMessage;
//import org.xtreemfs.foundation.flease.proposer.FleaseListener;
//
///**
// * Simulator for testing
// * @author bjko
// */
//public class FleaseMultiSim {
//
// //private void
//
// /**
// * @param args the command line arguments
// */
// public static void main(String[] args) {
// try {
//
// final boolean DEBUG_COMM_MSGS = false;
//
// final int dmax = 500;
// final int leaseTimeout = 10000;
//
// final int numHosts = 10;
// final int numConcurrentProposers = 10;
// final FleaseStage[] stages = new FleaseStage[numHosts];
//
// Logging.start(Logging.LEVEL_DEBUG, Category.all);
// TimeSync.initializeLocal(10000, 50);
//
// final Communicator com = new Communicator(10, 10, 2000, 5, true, 0.05, 0.05, DEBUG_COMM_MSGS);
// com.start();
//
// List<InetSocketAddress> allPorts = new ArrayList(numHosts);
// List<InetSocketAddress>[] acceptors = new List[numHosts];
//
// for (int i = 0; i < numHosts; i++) {
// final int portNo = 1024+i;
// FleaseConfig cfg = new FleaseConfig(leaseTimeout, dmax, 500, new InetSocketAddress(portNo), "localhost:"+(1024+i),5);
// stages[i] = new FleaseStage(cfg, "/tmp/xtreemfs-test", new FleaseMessageSenderInterface() {
//
// public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
// assert(message != null);
// if (DEBUG_COMM_MSGS)
// Logging.logMessage(Logging.LEVEL_DEBUG, this,"received message for delivery to port %d: %s",recipient.getPort(),message.toString());
// message.setSender(new InetSocketAddress("localhost", portNo));
// com.send(recipient.getPort(), message);
// }
// }, true, new FleaseViewChangeListenerInterface() {
//
// public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
// //ignore
// }
// },null);
// stages[i].setLifeCycleListener(new LifeCycleListener() {
//
// public void startupPerformed() {
// }
//
// public void shutdownPerformed() {
// }
//
// public void crashPerformed(Throwable cause) {
// cause.printStackTrace();
// System.exit(100);
// }
// });
// stages[i].start();
// allPorts.add(new InetSocketAddress("localhost", 1024+i));
// com.openPort(1024+i, stages[i]);
// }
//
// for (int i = 0; i < numHosts; i++) {
// final int portNo = 1024+i;
// acceptors[i] = new ArrayList(numHosts-1);
// for (InetSocketAddress ia : allPorts) {
// if (ia.getPort() != portNo)
// acceptors[i].add(ia);
// }
// stages[i].openCell(new ASCIIString("testcell"), acceptors[i],true);
// }
//
// //do something
//
// do {
// final List<LInfo> results = new ArrayList(numHosts);
// final Semaphore s = new Semaphore(0);
//
//
// final List<Integer> hostNumbers = new ArrayList(numHosts);
// for (int i = 0; i < numHosts; i++)
// hostNumbers.add(i);
//
// while (hostNumbers.size()+numConcurrentProposers > numHosts) {
// final int tmp = (int)(Math.random()*hostNumbers.size());
// final int host = hostNumbers.remove((int)tmp);
// stages[host].getLease(new ASCIIString("testcell"), new FleaseListener() {
//
// public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms) {
// final ASCIIString id = stages[host].getIdentity();
// synchronized (results) {
// LInfo i = new LInfo();
// i.host = id;
// i.owner = leaseHolder;
// i.to = leaseTimeout_ms;
// results.add(i);
// }
// s.release();
// System.out.println("host: "+id+". lease result: "+leaseHolder+"/"+leaseTimeout_ms);
// }
//
// public void proposalFailed(ASCIIString cellId, Throwable cause) {
// final ASCIIString id = stages[host].getIdentity();
// System.out.println("host: "+id+". lease failed: "+cause);
// s.release();
// }
// });
// }
// System.out.println("all started");
//
// if (!s.tryAcquire(numConcurrentProposers, 30000, TimeUnit.MILLISECONDS)) {
// throw new RuntimeException("timed out waiting for semaphore");
// }
//
// System.out.println("all results available");
// final long now = TimeSync.getGlobalTime();
//
// //first: remove all leases which are timed out
// Iterator<LInfo> iter = results.iterator();
// while (iter.hasNext()) {
// LInfo i = iter.next();
// if (i.to+dmax < now) {
// iter.remove();
// }
// }
//
// //now check all the values
// ASCIIString owner = null;
// LInfo other = null;
// boolean violated = false;
// for (LInfo i : results) {
// if (owner == null) {
// owner = i.owner;
// other = i;
// } else {
// if (!owner.equals(i.owner)) {
// com.shutdown();
// Map<Thread,StackTraceElement[]> traces = Thread.getAllStackTraces();
// System.out.println("INVARIANT VIOLATED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
// System.out.println("\n\n");
// System.out.println(i.host+" has : "+i.owner+"/"+i.to);
// System.out.println(other.host+" has : "+other.owner+"/"+other.to);
//
// for (int j = 0; j < numHosts; j++) {
// System.out.println(stages[j]._dump_acceptor_state(new ASCIIString("testcell")));
// }
//
// System.out.println("");
// for (Thread t : traces.keySet()) {
// System.out.println("Thread: "+t.getName());
// final StackTraceElement[] e = traces.get(t);
// for (StackTraceElement elem : e) {
// System.out.println(elem.toString());
// }
// }
// System.exit(2);
// }
// }
// }
//
//
// //make sure that cells also time out some times (requires a wait > 2*lease_timeout)
// final int waitTime = (int)(Math.random()*(leaseTimeout*2+2000+dmax));
// System.out.println("waiting for "+waitTime+"ms");
// Thread.sleep(waitTime);
// } while (true);
// /*
// for (int i = 0; i < numHosts; i++) {
// stages[i].shutdown();
// }
// com.shutdown();
// */
//
// } catch (Exception ex) {
// ex.printStackTrace();
// Map<Thread,StackTraceElement[]> traces = Thread.getAllStackTraces();
// System.out.println("");
// for (Thread t : traces.keySet()) {
// System.out.println("Thread: "+t.getName());
// final StackTraceElement[] e = traces.get(t);
// for (StackTraceElement elem : e) {
// System.out.println(elem.toString());
// }
// }
// System.exit(1);
// }
//
// }
//
// public static final class LInfo {
// ASCIIString host;
// ASCIIString owner;
// long to;
//
// }
//
//}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.sim;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.xtreemfs.foundation.LifeCycleListener;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.Flease;
import org.xtreemfs.foundation.flease.FleaseConfig;
import org.xtreemfs.foundation.flease.FleaseMessageSenderInterface;
import org.xtreemfs.foundation.flease.FleaseStage;
import org.xtreemfs.foundation.flease.FleaseStatusListener;
import org.xtreemfs.foundation.flease.FleaseViewChangeListenerInterface;
import org.xtreemfs.foundation.flease.MasterEpochHandlerInterface;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.proposer.FleaseException;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
/**
* Simulator for testing
* @author bjko
*/
public class FleaseSim {
//private void
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
final boolean DEBUG_COMM_MSGS = false;
final int dmax = 500;
final int leaseTimeout = 5000;
final int numHosts = 10;
final FleaseStage[] stages = new FleaseStage[numHosts];
final boolean useME = true;
Logging.start(Logging.LEVEL_DEBUG, Category.all);
TimeSync.initializeLocal(50);
final Communicator com = new Communicator(10, 100, 30000, 5, true, 0.2, 0.05, DEBUG_COMM_MSGS);
com.start();
List<InetSocketAddress> allPorts = new ArrayList(numHosts);
List<InetSocketAddress>[] acceptors = new List[numHosts];
MasterEpochHandlerInterface[] meHandlers = new MasterEpochHandlerInterface[numHosts];
final AtomicReference<Flease>[] leaseStates = new AtomicReference[numHosts];
for (int i = 0; i < numHosts; i++) {
final int portNo = 1024+i;
final int myI = i;
FleaseConfig cfg = new FleaseConfig(leaseTimeout, dmax, 500, new InetSocketAddress(portNo), "localhost:"+(1024+i),5, true, 0, true);
leaseStates[i] = new AtomicReference<Flease>(Flease.EMPTY_LEASE);
if (useME) {
meHandlers[i] = new MasterEpochHandlerInterface() {
long me = 0;
public long getMasterEpoch() {
return me;
}
@Override
public void sendMasterEpoch(FleaseMessage response, Continuation callback) {
response.setMasterEpochNumber(me);
callback.processingFinished();
}
@Override
public void storeMasterEpoch(FleaseMessage request, Continuation callback) {
me = request.getMasterEpochNumber();
callback.processingFinished();
}
};
}
stages[i] = new FleaseStage(cfg, "/tmp/xtreemfs-test", new FleaseMessageSenderInterface() {
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
assert(message != null);
if (DEBUG_COMM_MSGS)
Logging.logMessage(Logging.LEVEL_DEBUG, this,"received message for delivery to port %d: %s",recipient.getPort(),message.toString());
message.setSender(new InetSocketAddress("localhost", portNo));
com.send(recipient.getPort(), message);
}
}, true, new FleaseViewChangeListenerInterface() {
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
public void statusChanged(ASCIIString cellId, Flease lease) {
synchronized (leaseStates) {
leaseStates[myI].set(lease);
}
System.out.println("state change for "+portNo+": "+lease.getLeaseHolder()+"/"+lease.getLeaseTimeout_ms());
}
public void leaseFailed(ASCIIString cellId, FleaseException error) {
System.out.println("lease failed: "+error);
synchronized (leaseStates) {
leaseStates[myI].set(Flease.EMPTY_LEASE);
}
//restart my cell
}
},meHandlers[i]);
stages[i].setLifeCycleListener(new LifeCycleListener() {
public void startupPerformed() {
}
public void shutdownPerformed() {
}
public void crashPerformed(Throwable cause) {
cause.printStackTrace();
System.exit(100);
}
});
stages[i].start();
allPorts.add(new InetSocketAddress("localhost", 1024+i));
com.openPort(1024+i, stages[i]);
}
for (int i = 0; i < numHosts; i++) {
final int portNo = 1024+i;
acceptors[i] = new ArrayList(numHosts-1);
for (InetSocketAddress ia : allPorts) {
if (ia.getPort() != portNo)
acceptors[i].add(ia);
}
stages[i].openCell(new ASCIIString("testcell"), acceptors[i],false);
}
//do something
do {
final AtomicBoolean sync = new AtomicBoolean();
final AtomicReference<ASCIIString> ref = new AtomicReference();
Thread.sleep(100);
System.out.print("checking local states: ");
ASCIIString leaseHolder = null;
int leaseInstanceId = 0;
synchronized (leaseStates) {
for (int i = 0; i < numHosts; i++) {
if (!leaseStates[i].get().isEmptyLease()) {
if (leaseHolder == null) {
leaseHolder = leaseStates[i].get().getLeaseHolder();
} else {
if (!leaseHolder.equals(leaseStates[i].get().getLeaseHolder())) {
com.shutdown();
System.out.println("INVARIANT VIOLATED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
System.out.println("\n\n");
System.out.println("got lease for: "+leaseHolder);
System.out.println("but host "+i+" learned "+leaseStates[i].get().getLeaseHolder());
for (int j = 0; j < numHosts; j++) {
System.out.println(stages[j]._dump_acceptor_state(new ASCIIString("testcell")));
System.out.println("signalled result: "+leaseStates[j].get());
System.out.println(" valid: "+leaseStates[j].get().isValid());
}
System.exit(2);
} else {
System.out.print("+");
}
}
} else {
System.out.print("o");
}
}
}
System.out.println("");
final int host = (int)(Math.random()*numHosts);
stages[host].closeCell(new ASCIIString("testcell"), false);
//make sure that cells also time out some times (requires a wait > 2*lease_timeout)
final int waitTime = (int)(Math.random()*(leaseTimeout*2+1000));
System.out.println("waiting for "+waitTime+"ms");
Thread.sleep(waitTime);
stages[host].openCell(new ASCIIString("testcell"), acceptors[host],false);
} while (true);
/*
for (int i = 0; i < numHosts; i++) {
stages[i].shutdown();
}
com.shutdown();
*/
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.proposer.FleaseException;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
import org.xtreemfs.foundation.util.FSUtils;
/**
*
* @author bjko
*/
public class FleaseStageTest {
private static FleaseConfig cfg;
private static File testDir;
@BeforeClass
public static void setUpClass() {
Logging.start(Logging.LEVEL_WARN, Category.all);
TimeSync.initializeLocal(50);
cfg = new FleaseConfig(10000, 500, 500, new InetSocketAddress(12345), "localhost:12345",5);
testDir = new File("/tmp/xtreemfs-test/");
}
@Before
public void setUp() throws Exception {
FSUtils.delTree(testDir);
testDir.mkdirs();
}
@After
public void tearDown() throws Exception {
}
/**
* Test of createTimer method, of class FleaseStage.
*/
@Test
public void testOpenAndGetLease() throws Exception {
final ASCIIString CELL_ID = new ASCIIString("testcell");
final AtomicReference<Flease> result = new AtomicReference();
FleaseStage fs = new FleaseStage(cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() {
@Override
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
//ignore me
}
}, true, new FleaseViewChangeListenerInterface() {
@Override
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
// System.out.println("state change: "+cellId+" owner="+lease.getLeaseHolder());
synchronized (result) {
result.set(new Flease(cellId, lease.getLeaseHolder(), lease.getLeaseTimeout_ms(),lease.getMasterEpochNumber()));
result.notify();
}
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
fail(error.toString());
}
}, null);
FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART);
msg.setCellId(CELL_ID);
fs.start();
fs.waitForStartup();
fs.openCell(CELL_ID, new ArrayList(),false);
synchronized(result) {
if (result.get() == null)
result.wait(1000);
if (result.get() == null)
fail("timeout!");
}
assertEquals(result.get().getLeaseHolder(),cfg.getIdentity());
FleaseFuture f = fs.closeCell(CELL_ID, false);
f.get();
Thread.sleep(12000);
result.set(null);
fs.openCell(CELL_ID, new ArrayList(), false);
synchronized(result) {
if (result.get() == null)
result.wait(1000);
if (result.get() == null)
fail("timeout!");
}
assertEquals(result.get().getLeaseHolder(),cfg.getIdentity());
fs.shutdown();
fs.waitForShutdown();
}
/**
* Test of createTimer method, of class FleaseStage.
*/
@Test
public void testGetState() throws Exception {
FleaseStage fs = new FleaseStage(cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() {
@Override
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
//ignore me
}
}, true, new FleaseViewChangeListenerInterface() {
@Override
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
fail(error.toString());
}
}, null);
FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART);
msg.setCellId(new ASCIIString("testcell"));
fs.start();
fs.waitForStartup();
FleaseFuture f = fs.openCell(new ASCIIString("testcell"), new ArrayList(), false);
final AtomicBoolean done = new AtomicBoolean(false);
f.get();
Thread.sleep(100);
Map<ASCIIString,FleaseMessage> m = fs.getLocalState();
// for (ASCIIString cellId : m.keySet()) {
// System.out.println("cell "+cellId+" "+m.get(cellId));
// }
fs.shutdown();
fs.waitForShutdown();
}
/**
* Test of createTimer method, of class FleaseStage.
*/
@Test
public void testCreateTimer() throws Exception {
FleaseStage fs = new FleaseStage(cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() {
@Override
public void sendMessage(FleaseMessage messages, InetSocketAddress recipient) {
//ignore me
}
}, true, new FleaseViewChangeListenerInterface() {
@Override
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
throw new UnsupportedOperationException("Not supported yet.");
}
}, null);
FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART);
msg.setCellId(new ASCIIString("testcell"));
fs.start();
fs.waitForStartup();
fs.createTimer(msg, TimeSync.getLocalSystemTime()+20);
Thread.sleep(100);
fs.shutdown();
fs.waitForShutdown();
}
}

View File

@@ -0,0 +1,280 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.proposer.FleaseException;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
import org.xtreemfs.foundation.util.FSUtils;
/**
*
* @author bjko
*/
public class MasterEpochTest {
private static FleaseConfig cfg;
private static File testDir;
@BeforeClass
public static void setUpClass() {
Logging.start(Logging.LEVEL_WARN, Category.all);
TimeSync.initializeLocal(50);
cfg = new FleaseConfig(10000, 500, 500, new InetSocketAddress(12345), "localhost:12345",5, true, 0, true);
testDir = new File("/tmp/xtreemfs-test/");
}
@Before
public void setUp() throws Exception {
FSUtils.delTree(testDir);
testDir.mkdirs();
}
@After
public void tearDown() throws Exception {
}
/**
* Test of createTimer method, of class FleaseStage.
*/
@Test
public void testOpenAndGetLease() throws Exception {
final ASCIIString CELL_ID = new ASCIIString("testcell");
final AtomicReference<Flease> result = new AtomicReference();
FleaseStage fs = new FleaseStage(cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() {
@Override
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
//ignore me
}
}, true, new FleaseViewChangeListenerInterface() {
@Override
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
// System.out.println("state change: "+cellId+" owner="+lease.getLeaseHolder());
synchronized (result) {
result.set(new Flease(cellId, lease.getLeaseHolder(), lease.getLeaseTimeout_ms(),lease.getMasterEpochNumber()));
result.notify();
}
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
fail(error.toString());
}
}, new MasterEpochHandlerInterface() {
long masterEpochNum = 0;
@Override
public void sendMasterEpoch(FleaseMessage response, Continuation callback) {
// System.out.println("sending: "+masterEpochNum);
response.setMasterEpochNumber(masterEpochNum);
callback.processingFinished();
}
@Override
public void storeMasterEpoch(FleaseMessage request, Continuation callback) {
masterEpochNum = request.getMasterEpochNumber();
// System.out.println("storing: "+masterEpochNum);
callback.processingFinished();
}
});
FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART);
msg.setCellId(CELL_ID);
fs.start();
fs.waitForStartup();
fs.openCell(CELL_ID, new ArrayList(),true);
synchronized(result) {
if (result.get() == null)
result.wait(1000);
if (result.get() == null)
fail("timeout!");
}
assertEquals(result.get().getLeaseHolder(),cfg.getIdentity());
assertEquals(result.get().getMasterEpochNumber(),1);
FleaseFuture f = fs.closeCell(CELL_ID, false);
f.get();
Thread.sleep(12000);
result.set(null);
fs.openCell(CELL_ID, new ArrayList(), true);
synchronized(result) {
if (result.get() == null)
result.wait(1000);
if (result.get() == null)
fail("timeout!");
}
assertEquals(result.get().getLeaseHolder(),cfg.getIdentity());
assertEquals(result.get().getMasterEpochNumber(),2);
fs.shutdown();
fs.waitForShutdown();
}
/**
* Test of createTimer method, of class FleaseStage.
*/
@Test
public void testSimpleMasterEpochHandler() throws Exception {
final ASCIIString CELL_ID = new ASCIIString("testcell");
final AtomicReference<Flease> result = new AtomicReference();
SimpleMasterEpochHandler meHandler = new SimpleMasterEpochHandler("/tmp/xtreemfs-test/");
meHandler.start();
meHandler.waitForStartup();
FleaseStage fs = new FleaseStage(cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() {
@Override
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
//ignore me
}
}, true, new FleaseViewChangeListenerInterface() {
@Override
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
// System.out.println("state change: "+cellId+" owner="+lease.getLeaseHolder());
synchronized (result) {
result.set(new Flease(cellId, lease.getLeaseHolder(), lease.getLeaseTimeout_ms(),lease.getMasterEpochNumber()));
result.notify();
}
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
fail(error.toString());
}
}, meHandler);
FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART);
msg.setCellId(CELL_ID);
fs.start();
fs.waitForStartup();
fs.openCell(CELL_ID, new ArrayList(),true);
synchronized(result) {
if (result.get() == null)
result.wait(1000);
if (result.get() == null)
fail("timeout!");
}
assertEquals(result.get().getLeaseHolder(),cfg.getIdentity());
assertEquals(1, result.get().getMasterEpochNumber());
FleaseFuture f = fs.closeCell(CELL_ID, false);
f.get();
fs.shutdown();
fs.waitForShutdown();
meHandler.shutdown();
meHandler.waitForShutdown();
Thread.sleep(12000);
//restart
meHandler = new SimpleMasterEpochHandler("/tmp/xtreemfs-test/");
meHandler.start();
meHandler.waitForStartup();
fs = new FleaseStage(cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() {
@Override
public void sendMessage(FleaseMessage message, InetSocketAddress recipient) {
//ignore me
}
}, true, new FleaseViewChangeListenerInterface() {
@Override
public void viewIdChangeEvent(ASCIIString cellId, int viewId) {
}
},new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
// System.out.println("state change: "+cellId+" owner="+lease.getLeaseHolder());
synchronized (result) {
result.set(new Flease(cellId, lease.getLeaseHolder(), lease.getLeaseTimeout_ms(),lease.getMasterEpochNumber()));
result.notify();
}
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
fail(error.toString());
}
}, meHandler);
fs.start();
fs.waitForStartup();
result.set(null);
fs.openCell(CELL_ID, new ArrayList(), true);
synchronized(result) {
if (result.get() == null)
result.wait(1000);
if (result.get() == null)
fail("timeout!");
}
assertEquals(result.get().getLeaseHolder(),cfg.getIdentity());
assertEquals(result.get().getMasterEpochNumber(),2);
fs.shutdown();
fs.waitForShutdown();
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.acceptor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.File;
import java.net.InetSocketAddress;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.FleaseConfig;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.flease.comm.FleaseMessage.MsgType;
import org.xtreemfs.foundation.flease.comm.ProposalNumber;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
import org.xtreemfs.foundation.util.FSUtils;
/**
*
* @author bjko
*/
public class FleaseAcceptorTest {
private FleaseAcceptor acceptor;
private final static ASCIIString TESTCELL = new ASCIIString("testcell");
private static FleaseConfig cfg;
private static File testDir;
@BeforeClass
public static void setUpClass() {
testDir = new File("/tmp/xtreemfs-test/");
FSUtils.delTree(testDir);
testDir.mkdirs();
Logging.start(Logging.LEVEL_WARN, Category.all);
TimeSync.initializeLocal(50);
cfg = new FleaseConfig(10000, 500, 500, new InetSocketAddress(12345), "localhost:12345",1);
}
@Before
public void setUp() throws Exception {
acceptor = new FleaseAcceptor(new LearnEventListener() {
@Override
public void learnedEvent(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long me) {
}
}, cfg, "/tmp/xtreemfs-test/", true);
}
@After
public void tearDown() throws Exception {
acceptor.shutdown();
}
@Test
public void testPrepAccLearn() {
FleaseMessage prep = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE);
prep.setCellId(TESTCELL);
prep.setProposalNo(new ProposalNumber(1, 1));
prep.setSendTimestamp(TimeSync.getLocalSystemTime());
prep.setLeaseTimeout(TimeSync.getLocalSystemTime()+10000);
prep.setLeaseHolder(new ASCIIString("me"));
FleaseMessage response = acceptor.processMessage(prep);
assertEquals(MsgType.MSG_PREPARE_ACK,response.getMsgType());
prep = new FleaseMessage(MsgType.MSG_ACCEPT,prep);
prep.setSendTimestamp(TimeSync.getLocalSystemTime());
response = acceptor.processMessage(prep);
assertEquals(MsgType.MSG_ACCEPT_ACK,response.getMsgType());
prep = new FleaseMessage(MsgType.MSG_LEARN,prep);
prep.setSendTimestamp(TimeSync.getLocalSystemTime());
response = acceptor.processMessage(prep);
assertNull(response);
}
@Test
public void testConcurrentProposal() {
FleaseMessage prep1 = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE);
prep1.setCellId(TESTCELL);
prep1.setProposalNo(new ProposalNumber(1, 1));
prep1.setSendTimestamp(TimeSync.getLocalSystemTime());
prep1.setLeaseTimeout(TimeSync.getLocalSystemTime()+10000);
prep1.setLeaseHolder(new ASCIIString("me1"));
FleaseMessage prep2 = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE);
prep2.setCellId(TESTCELL);
prep2.setProposalNo(new ProposalNumber(1, 2));
prep2.setSendTimestamp(TimeSync.getLocalSystemTime());
prep2.setLeaseTimeout(TimeSync.getLocalSystemTime()+10000);
prep2.setLeaseHolder(new ASCIIString("me2"));
FleaseMessage response = acceptor.processMessage(prep1);
assertEquals(MsgType.MSG_PREPARE_ACK,response.getMsgType());
response = acceptor.processMessage(prep2);
assertEquals(MsgType.MSG_PREPARE_ACK,response.getMsgType());
prep1 = new FleaseMessage(MsgType.MSG_ACCEPT,prep1);
prep1.setSendTimestamp(TimeSync.getLocalSystemTime());
response = acceptor.processMessage(prep1);
assertEquals(MsgType.MSG_ACCEPT_NACK,response.getMsgType());
}
@Test
public void testGetLease() {
FleaseMessage prep2 = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE);
prep2.setCellId(TESTCELL);
prep2.setProposalNo(new ProposalNumber(1, 2));
prep2.setSendTimestamp(TimeSync.getLocalSystemTime());
prep2.setLeaseTimeout(TimeSync.getLocalSystemTime()+10000);
prep2.setLeaseHolder(new ASCIIString("me2"));
FleaseMessage response = acceptor.processMessage(prep2);
assertEquals(MsgType.MSG_PREPARE_ACK,response.getMsgType());
prep2 = new FleaseMessage(MsgType.MSG_ACCEPT,prep2);
prep2.setSendTimestamp(TimeSync.getLocalSystemTime());
response = acceptor.processMessage(prep2);
assertEquals(MsgType.MSG_ACCEPT_ACK,response.getMsgType());
FleaseMessage lease = acceptor.getLocalLeaseInformation(TESTCELL);
assertNull(lease);
prep2 = new FleaseMessage(MsgType.MSG_LEARN,prep2);
prep2.setSendTimestamp(TimeSync.getLocalSystemTime());
response = acceptor.processMessage(prep2);
assertNull(response);
lease = acceptor.getLocalLeaseInformation(TESTCELL);
assertNotNull(lease);
assertEquals(new ASCIIString("me2"),lease.getLeaseHolder());
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.comm;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import static org.junit.Assert.*;
/**
*
* @author bjko
*/
public class FleaseMessageTest {
public FleaseMessageTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Test
public void testSerialization() throws Exception {
FleaseMessage m1 = new FleaseMessage(FleaseMessage.MsgType.MSG_LEARN);
m1.setCellId(new ASCIIString("testcell"));
m1.setLeaseHolder(new ASCIIString("yagga"));
m1.setLeaseTimeout(123456789l);
m1.setPrevProposalNo(new ProposalNumber(12, 178743687));
m1.setProposalNo(new ProposalNumber(15, 736456));
m1.setSendTimestamp(49789834);
m1.setViewId(55685);
m1.setMasterEpochNumber(52455115211l);
final int size = m1.getSize();
ReusableBuffer rb = BufferPool.allocate(size);
m1.serialize(rb);
rb.flip();
FleaseMessage m2 = new FleaseMessage(rb);
assertEquals(m1.getCellId(),m2.getCellId());
assertEquals(m1.getLeaseHolder(),m2.getLeaseHolder());
assertEquals(m1.getLeaseTimeout(),m2.getLeaseTimeout());
assertEquals(m1.getMsgType(),m2.getMsgType());
assertEquals(m1.getPrevProposalNo().getProposalNo(),m2.getPrevProposalNo().getProposalNo());
assertEquals(m1.getPrevProposalNo().getSenderId(),m2.getPrevProposalNo().getSenderId());
assertEquals(m1.getProposalNo().getProposalNo(),m2.getProposalNo().getProposalNo());
assertEquals(m1.getProposalNo().getSenderId(),m2.getProposalNo().getSenderId());
assertEquals(m1.getSendTimestamp(),m2.getSendTimestamp());
assertEquals(m1.getViewId(),m2.getViewId());
assertEquals(m1.getMasterEpochNumber(),m2.getMasterEpochNumber());
}
}

View File

@@ -0,0 +1,328 @@
/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.foundation.flease.proposer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xtreemfs.foundation.TimeSync;
import org.xtreemfs.foundation.buffer.ASCIIString;
import org.xtreemfs.foundation.flease.Flease;
import org.xtreemfs.foundation.flease.FleaseConfig;
import org.xtreemfs.foundation.flease.FleaseStatusListener;
import org.xtreemfs.foundation.flease.acceptor.FleaseAcceptor;
import org.xtreemfs.foundation.flease.acceptor.LearnEventListener;
import org.xtreemfs.foundation.flease.comm.FleaseCommunicationInterface;
import org.xtreemfs.foundation.flease.comm.FleaseMessage;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
import org.xtreemfs.foundation.util.FSUtils;
/**
*
* @author bjko
*/
public class FleaseProposerTest {
private FleaseAcceptor acceptor;
private FleaseProposer proposer;
private final static ASCIIString TESTCELL = new ASCIIString("testcell");
private static FleaseConfig cfg;
private static File testDir;
private static AtomicReference<Flease> result;
@BeforeClass
public static void setUpClass() throws Exception {
testDir = new File("/tmp/xtreemfs-test/");
FSUtils.delTree(testDir);
testDir.mkdirs();
result = new AtomicReference();
Logging.start(Logging.LEVEL_WARN, Category.all);
TimeSync.initializeLocal(50);
cfg = new FleaseConfig(10000, 500, 500, new InetSocketAddress(12345), "localhost:12345",5);
}
@Before
public void setUp() throws Exception {
acceptor = new FleaseAcceptor(new LearnEventListener() {
@Override
public void learnedEvent(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long me) {
}
}, cfg, "/tmp/xtreemfs-test/", true);
proposer = new FleaseProposer(cfg, acceptor, new FleaseCommunicationInterface() {
@Override
public void sendMessage(FleaseMessage msg, InetSocketAddress receiver) throws IOException {
}
@Override
public void requestTimer(FleaseMessage msg, long timestamp) {
if (msg.getMsgType() == FleaseMessage.MsgType.EVENT_RESTART) {
long wait = timestamp - TimeSync.getLocalSystemTime();
try {
Thread.sleep(wait);
} catch (InterruptedException ex) {
Logger.getLogger(FleaseProposerTest.class.getName()).log(Level.SEVERE, null, ex);
}
try {
proposer.processMessage(msg);
} catch (Exception ex) {
fail(ex.toString());
}
}
}
}, new FleaseStatusListener() {
@Override
public void statusChanged(ASCIIString cellId, Flease lease) {
// System.out.println("result: "+lease.getLeaseHolder());
synchronized (result) {
result.set(new Flease(cellId, lease.getLeaseHolder(), lease.getLeaseTimeout_ms(),lease.getMasterEpochNumber()));
result.notify();
}
}
@Override
public void leaseFailed(ASCIIString cellId, FleaseException error) {
// System.out.println("failed: "+error);
fail(error.toString());
}
}, new LearnEventListener() {
@Override
public void learnedEvent(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms, long me) {
throw new UnsupportedOperationException("Not supported yet.");
}
},null,null);
}
@After
public void tearDown() throws Exception {
}
@Test
public void testGetLease() throws Exception {
proposer.openCell(TESTCELL, new ArrayList(), false, 0);
Thread.sleep(100);
FleaseProposerCell cell = proposer.cells.get(TESTCELL);
assertEquals(TESTCELL,cell.getMessageSent().getCellId());
assertEquals(cfg.getIdentity(),cell.getMessageSent().getLeaseHolder());
assertTrue(cell.getMessageSent().getLeaseTimeout() > TimeSync.getGlobalTime());
}
/*public void testHandoverLease() throws Exception {
proposer.openCell(TESTCELL, new ArrayList(),false);
Thread.sleep(100);
FleaseProposerCell cell = proposer.cells.get(TESTCELL);
assertEquals(TESTCELL,cell.getMessageSent().getCellId());
assertEquals(cfg.getIdentity(),cell.getMessageSent().getLeaseHolder());
assertTrue(cell.getMessageSent().getLeaseTimeout() > TimeSync.getGlobalTime());
final ASCIIString HANDOVER = new ASCIIString("HANDOVER");
proposer.handoverLease(TESTCELL, HANDOVER);
Thread.sleep(100);
cell = proposer.cells.get(TESTCELL);
assertEquals(TESTCELL,cell.getMessageSent().getCellId());
assertEquals(HANDOVER,cell.getMessageSent().getLeaseHolder());
assertTrue(cell.getMessageSent().getLeaseTimeout() > TimeSync.getGlobalTime());
}*/
// public void testPriorProposal() throws Exception {
//
// final ASCIIString otherId = new ASCIIString("YAGGAYAGGA");
// final AtomicBoolean finished = new AtomicBoolean(false);
//
// //initialize the acceptor
// FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_ACCEPT);
// tmp.setCellId(TESTCELL);
// tmp.setProposalNo(new ProposalNumber(10, 123456));
// tmp.setLeaseHolder(otherId);
// tmp.setLeaseTimeout(TimeSync.getGlobalTime()-20000);
// tmp.setSendTimestamp(TimeSync.getGlobalTime());
// acceptor.processMessage(tmp);
//
// tmp.setCellId(TESTCELL);
// tmp.setProposalNo(new ProposalNumber(10, 123456));
// tmp.setLeaseTimeout(TimeSync.getGlobalTime()+10000);
// tmp.setSendTimestamp(TimeSync.getGlobalTime());
// acceptor.processMessage(tmp);
//
// proposer.openCell(TESTCELL, new ArrayList<InetSocketAddress>(),false);
//
// System.out.println("start acquire lease...");
// proposer.acquireLease(TESTCELL, new FleaseListener() {
//
// public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms) {
// System.out.println("got lease!");
// assertEquals(TESTCELL,cellId);
// assertEquals(otherId,leaseHolder);
// finished.set(true);
// }
//
// public void proposalFailed(ASCIIString cellId, Throwable cause) {
// System.out.println("failed!");
// fail(cause.toString());
// }
// });
//
//
// }
//
//
// public void testPriorProposal2() throws Exception {
//
// final ASCIIString otherId = new ASCIIString("YAGGAYAGGA");
// final AtomicBoolean finished = new AtomicBoolean(false);
//
// //initialize the acceptor
// FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_LEARN);
// tmp.setCellId(TESTCELL);
// tmp.setProposalNo(new ProposalNumber(10, 123456));
// tmp.setLeaseHolder(otherId);
// tmp.setLeaseTimeout(TimeSync.getGlobalTime()+10000);
// tmp.setSendTimestamp(TimeSync.getGlobalTime());
// acceptor.processMessage(tmp);
//
// tmp.setCellId(TESTCELL);
// tmp.setProposalNo(new ProposalNumber(10, 123456));
// tmp.setLeaseTimeout(TimeSync.getGlobalTime()+10000);
// tmp.setSendTimestamp(TimeSync.getGlobalTime());
// acceptor.processMessage(tmp);
//
// proposer.openCell(TESTCELL, new ArrayList<InetSocketAddress>(),false);
//
// System.out.println("start acquire lease...");
// proposer.acquireLease(TESTCELL, new FleaseListener() {
//
// public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms) {
// System.out.println("got lease!");
// assertEquals(TESTCELL,cellId);
// assertEquals(otherId,leaseHolder);
// finished.set(true);
// }
//
// public void proposalFailed(ASCIIString cellId, Throwable cause) {
// System.out.println("failed!");
// fail(cause.toString());
// }
// });
//
//
// }
//
// public void testValidLease() throws Exception {
//
// final ASCIIString otherId = new ASCIIString("YAGGAYAGGA");
// final AtomicBoolean finished = new AtomicBoolean(false);
//
// //initialize the acceptor
// FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_LEARN);
// tmp.setCellId(TESTCELL);
// tmp.setProposalNo(new ProposalNumber(10, 123456));
// tmp.setLeaseHolder(otherId);
// tmp.setLeaseTimeout(TimeSync.getGlobalTime()+10000);
// tmp.setSendTimestamp(TimeSync.getGlobalTime());
// acceptor.processMessage(tmp);
//
// proposer.openCell(TESTCELL, new ArrayList<InetSocketAddress>(),false);
//
// System.out.println("start acquire lease...");
// proposer.acquireLease(TESTCELL, new FleaseListener() {
//
// public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms) {
// System.out.println("got lease!");
// assertEquals(TESTCELL,cellId);
// assertEquals(otherId,leaseHolder);
// finished.set(true);
// }
//
// public void proposalFailed(ASCIIString cellId, Throwable cause) {
// System.out.println("failed!");
// fail(cause.toString());
// }
// });
// }
//
// public void testLeaseInGP() throws Exception {
//
// System.out.println("TEST testLeaseInGP");
//
// final ASCIIString otherId = new ASCIIString("YAGGAYAGGA");
// final AtomicBoolean finished = new AtomicBoolean(false);
//
// //initialize the acceptor
// FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_LEARN);
// tmp.setCellId(TESTCELL);
// tmp.setProposalNo(new ProposalNumber(10, 123456));
// tmp.setLeaseHolder(otherId);
// tmp.setLeaseTimeout(TimeSync.getGlobalTime()+100);
// tmp.setSendTimestamp(TimeSync.getGlobalTime());
// acceptor.processMessage(tmp);
//
// proposer.openCell(TESTCELL, new ArrayList<InetSocketAddress>(),false);
//
// System.out.println("start acquire lease...");
// proposer.acquireLease(TESTCELL, new FleaseListener() {
//
// public void proposalResult(ASCIIString cellId, ASCIIString leaseHolder, long leaseTimeout_ms) {
// System.out.println("got lease!");
// assertEquals(TESTCELL,cellId);
// assertEquals(cfg.getIdentity(),leaseHolder);
// finished.set(true);
// }
//
// public void proposalFailed(ASCIIString cellId, Throwable cause) {
// System.out.println("failed!");
// fail(cause.toString());
// }
// });
//
//
// }
}