Imported Upstream version 1.5.1
This commit is contained in:
75
java/flease/build-1.6.5.xml
Normal file
75
java/flease/build-1.6.5.xml
Normal 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
75
java/flease/build.xml
Normal 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>
|
||||
10
java/flease/eclipse-project/.classpath
Normal file
10
java/flease/eclipse-project/.classpath
Normal 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>
|
||||
18
java/flease/eclipse-project/.project
Normal file
18
java/flease/eclipse-project/.project
Normal 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
3
java/flease/manifest.mf
Normal file
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
||||
892
java/flease/nbproject/build-impl-1.6.5.xml
Normal file
892
java/flease/nbproject/build-impl-1.6.5.xml
Normal 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 "${ant.java.version}"/>
|
||||
<condition property="have-jdk-older-than-1.4">
|
||||
<or>
|
||||
<contains string="${version-output}" substring="java version "1.0"/>
|
||||
<contains string="${version-output}" substring="java version "1.1"/>
|
||||
<contains string="${version-output}" substring="java version "1.2"/>
|
||||
<contains string="${version-output}" substring="java version "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>
|
||||
1054
java/flease/nbproject/build-impl.xml
Normal file
1054
java/flease/nbproject/build-impl.xml
Normal file
File diff suppressed because it is too large
Load Diff
11
java/flease/nbproject/genfiles.properties
Normal file
11
java/flease/nbproject/genfiles.properties
Normal 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
|
||||
0
java/flease/nbproject/private/config.properties
Normal file
0
java/flease/nbproject/private/config.properties
Normal file
6
java/flease/nbproject/private/private.properties
Normal file
6
java/flease/nbproject/private/private.properties
Normal 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
|
||||
5
java/flease/nbproject/private/private.xml
Normal file
5
java/flease/nbproject/private/private.xml
Normal 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>
|
||||
141
java/flease/nbproject/private/profiler/configurations.xml
Normal file
141
java/flease/nbproject/private/profiler/configurations.xml
Normal 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>
|
||||
131
java/flease/nbproject/profiler-build-impl.xml
Normal file
131
java/flease/nbproject/profiler-build-impl.xml
Normal 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>
|
||||
73
java/flease/nbproject/project.properties
Normal file
73
java/flease/nbproject/project.properties
Normal 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
|
||||
24
java/flease/nbproject/project.xml
Normal file
24
java/flease/nbproject/project.xml
Normal 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>
|
||||
2
java/flease/nbproject/protobuf-build.cfg.xml
Normal file
2
java/flease/nbproject/protobuf-build.cfg.xml
Normal 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>
|
||||
24
java/flease/nbproject/protobuf-build.xml
Normal file
24
java/flease/nbproject/protobuf-build.xml
Normal 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>
|
||||
93
java/flease/src/org/xtreemfs/foundation/flease/Flease.java
Normal file
93
java/flease/src/org/xtreemfs/foundation/flease/Flease.java
Normal 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;
|
||||
}
|
||||
}
|
||||
191
java/flease/src/org/xtreemfs/foundation/flease/FleaseConfig.java
Normal file
191
java/flease/src/org/xtreemfs/foundation/flease/FleaseConfig.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
691
java/flease/src/org/xtreemfs/foundation/flease/FleaseStage.java
Normal file
691
java/flease/src/org/xtreemfs/foundation/flease/FleaseStage.java
Normal 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);
|
||||
}
|
||||
}
|
||||
122
java/flease/src/org/xtreemfs/foundation/flease/FleaseStats.java
Normal file
122
java/flease/src/org/xtreemfs/foundation/flease/FleaseStats.java
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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+")";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()+")";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 +")"
|
||||
: "");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
//
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
// }
|
||||
// });
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user