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());
|
||||
// }
|
||||
// });
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
75
java/foundation/build-1.6.5.xml
Normal file
75
java/foundation/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="Foundation" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project Foundation as part of the XtreemFS project.</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="XtreemFS-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>
|
||||
74
java/foundation/build-before-profiler.xml
Normal file
74
java/foundation/build-before-profiler.xml
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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="Foundation" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project Foundation as part of the XtreemFS project.</description>
|
||||
<import file="nbproject/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="XtreemFS-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>
|
||||
89
java/foundation/build.xml
Normal file
89
java/foundation/build.xml
Normal file
@@ -0,0 +1,89 @@
|
||||
<?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="Foundation" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project Foundation as part of the XtreemFS project.</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="XtreemFS-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.
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
This target is required by the BabuDB replication plugin which uses only a subset
|
||||
of the foundation code (the PBRPC communication infrastructure).
|
||||
The generated .jar file contains the required files of the subset.
|
||||
-->
|
||||
<target name="pbrpc-jar" depends="compile">
|
||||
<echo level="info">Creating PBRPC.jar.</echo>
|
||||
<!-- Create a new JAR. -->
|
||||
<jar destfile="dist/PBRPC.jar" basedir="build/classes">
|
||||
<include name="org/xtreemfs/foundation/pbrpc/**/*.class"/>
|
||||
<zipfileset dir="../../" includes="LICENSE" fullpath="/LICENSE"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
11
java/foundation/eclipse-project/.classpath
Normal file
11
java/foundation/eclipse-project/.classpath
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="../lib/protobuf-java-2.5.0.jar"/>
|
||||
<classpathentry kind="lib" path="../lib/test/junit-4.11.jar"/>
|
||||
<classpathentry kind="lib" path="../lib/test/hamcrest-core-1.3.jar"/>
|
||||
<classpathentry kind="lib" path="../lib/commons-codec-1.3.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
17
java/foundation/eclipse-project/.project
Normal file
17
java/foundation/eclipse-project/.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>xtreemfs_foundation</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
682
java/foundation/nbproject/build-impl-1.6.5.xml
Normal file
682
java/foundation/nbproject/build-impl-1.6.5.xml
Normal file
@@ -0,0 +1,682 @@
|
||||
<?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="XtreemFS-foundation-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"/>
|
||||
<condition property="manifest.available+main.class">
|
||||
<and>
|
||||
<isset property="manifest.available"/>
|
||||
<isset property="main.class"/>
|
||||
<not>
|
||||
<equals arg1="${main.class}" arg2="" trim="true"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="manifest.available+main.class+mkdist.available">
|
||||
<and>
|
||||
<istrue value="${manifest.available+main.class}"/>
|
||||
<isset property="libs.CopyLibs.classpath"/>
|
||||
</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}"/>
|
||||
<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>
|
||||
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
|
||||
<and>
|
||||
<isset property="jaxws.endorsed.dir"/>
|
||||
<available file="nbproject/jaxws-build.xml"/>
|
||||
</and>
|
||||
</condition>
|
||||
</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 name="-init-macrodef-javac">
|
||||
<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="${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}"/>
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
|
||||
<src>
|
||||
<dirset dir="@{gensrcdir}">
|
||||
<include name="*"/>
|
||||
</dirset>
|
||||
</src>
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
|
||||
<customize/>
|
||||
</javac>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<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="," property="javac.includes.binary">
|
||||
<path>
|
||||
<filelist dir="@{destdir}" files="${javac.includes}"/>
|
||||
</path>
|
||||
<globmapper from="*.java" to="*.class"/>
|
||||
</pathconvert>
|
||||
<delete>
|
||||
<files includes="${javac.includes.binary}"/>
|
||||
</delete>
|
||||
</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">
|
||||
<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="${run.jvmargs}"/>
|
||||
</junit>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target 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="dt_socket">
|
||||
<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>
|
||||
</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="${debug-args-line}"/>
|
||||
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
|
||||
<jvmarg value="-Dfile.encoding=${source.encoding}"/>
|
||||
<redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.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 value="-Dfile.encoding=${source.encoding}"/>
|
||||
<redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.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-presetdef-jar">
|
||||
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<jar compress="${jar.compress}" jarfile="${dist.jar}">
|
||||
<j2seproject1:fileset dir="${build.classes.dir}"/>
|
||||
</jar>
|
||||
</presetdef>
|
||||
</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" name="init"/>
|
||||
<!--
|
||||
===================
|
||||
COMPILATION SECTION
|
||||
===================
|
||||
-->
|
||||
<target depends="init" name="deps-jar" unless="no.deps"/>
|
||||
<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,-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 name="-post-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-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,-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" name="-do-jar-without-manifest" unless="manifest.available">
|
||||
<j2seproject1:jar/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="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="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" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
|
||||
<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}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main.class}"/>
|
||||
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||
</manifest>
|
||||
</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" if="libs.CopyLibs.classpath" name="-do-jar-with-libraries-without-manifest" unless="manifest.available+main.class">
|
||||
<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}" jarfile="${dist.jar}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</copylibs>
|
||||
</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,-do-jar-with-libraries-without-manifest,-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,-do-not-recompile,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,-do-not-recompile,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,-do-not-recompile,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,-do-not-recompile,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" 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>
|
||||
</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 classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.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">
|
||||
<!-- 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 classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" 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,-do-not-recompile,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,-do-not-recompile,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 depends="init" name="deps-clean" unless="no.deps"/>
|
||||
<target depends="init" name="-do-clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</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"/>
|
||||
</project>
|
||||
687
java/foundation/nbproject/build-impl.xml
Normal file
687
java/foundation/nbproject/build-impl.xml
Normal file
@@ -0,0 +1,687 @@
|
||||
<?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="XtreemFS-foundation-impl">
|
||||
<fail message="Please build using Ant 1.7.1 or higher.">
|
||||
<condition>
|
||||
<not>
|
||||
<antversion atleast="1.7.1"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
<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"/>
|
||||
<condition property="manifest.available+main.class">
|
||||
<and>
|
||||
<isset property="manifest.available"/>
|
||||
<isset property="main.class"/>
|
||||
<not>
|
||||
<equals arg1="${main.class}" arg2="" trim="true"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="manifest.available+main.class+mkdist.available">
|
||||
<and>
|
||||
<istrue value="${manifest.available+main.class}"/>
|
||||
<isset property="libs.CopyLibs.classpath"/>
|
||||
</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}"/>
|
||||
<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>
|
||||
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
|
||||
<and>
|
||||
<isset property="jaxws.endorsed.dir"/>
|
||||
<available file="nbproject/jaxws-build.xml"/>
|
||||
</and>
|
||||
</condition>
|
||||
</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 name="-init-macrodef-javac">
|
||||
<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="${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}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
|
||||
<src>
|
||||
<dirset dir="@{gensrcdir}" erroronmissingdir="false">
|
||||
<include name="*"/>
|
||||
</dirset>
|
||||
</src>
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
|
||||
<customize/>
|
||||
</javac>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<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="," property="javac.includes.binary">
|
||||
<path>
|
||||
<filelist dir="@{destdir}" files="${javac.includes}"/>
|
||||
</path>
|
||||
<globmapper from="*.java" to="*.class"/>
|
||||
</pathconvert>
|
||||
<delete>
|
||||
<files includes="${javac.includes.binary}"/>
|
||||
</delete>
|
||||
</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">
|
||||
<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="${run.jvmargs}"/>
|
||||
</junit>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target 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="dt_socket">
|
||||
<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>
|
||||
</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="${debug-args-line}"/>
|
||||
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
|
||||
<jvmarg value="-Dfile.encoding=${source.encoding}"/>
|
||||
<redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.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 value="-Dfile.encoding=${source.encoding}"/>
|
||||
<redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.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-presetdef-jar">
|
||||
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<jar compress="${jar.compress}" jarfile="${dist.jar}">
|
||||
<j2seproject1:fileset dir="${build.classes.dir}"/>
|
||||
</jar>
|
||||
</presetdef>
|
||||
</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" name="init"/>
|
||||
<!--
|
||||
===================
|
||||
COMPILATION SECTION
|
||||
===================
|
||||
-->
|
||||
<target depends="init" name="deps-jar" unless="no.deps"/>
|
||||
<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,-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 name="-post-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-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,-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" name="-do-jar-without-manifest" unless="manifest.available">
|
||||
<j2seproject1:jar/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="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="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" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
|
||||
<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}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main.class}"/>
|
||||
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||
</manifest>
|
||||
</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" if="libs.CopyLibs.classpath" name="-do-jar-with-libraries-without-manifest" unless="manifest.available+main.class">
|
||||
<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}" jarfile="${dist.jar}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</copylibs>
|
||||
</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,-do-jar-with-libraries-without-manifest,-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,-do-not-recompile,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,-do-not-recompile,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,-do-not-recompile,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,-do-not-recompile,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" 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>
|
||||
</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 classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.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">
|
||||
<!-- 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 classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" 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,-do-not-recompile,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,-do-not-recompile,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 depends="init" name="deps-clean" unless="no.deps"/>
|
||||
<target depends="init" name="-do-clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</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"/>
|
||||
</project>
|
||||
11
java/foundation/nbproject/genfiles.properties
Normal file
11
java/foundation/nbproject/genfiles.properties
Normal file
@@ -0,0 +1,11 @@
|
||||
build.xml.data.CRC32=4a9eff70
|
||||
build.xml.script.CRC32=ce2ddeb0
|
||||
build.xml.stylesheet.CRC32=958a1d3e
|
||||
# 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=beaaf17a
|
||||
nbproject/build-impl.xml.script.CRC32=3e4625c6
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=78c6a6ee@1.38.1.45
|
||||
nbproject/profiler-build-impl.xml.data.CRC32=4a9eff70
|
||||
nbproject/profiler-build-impl.xml.script.CRC32=abda56ed
|
||||
nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf
|
||||
131
java/foundation/nbproject/profiler-build-impl.xml
Normal file
131
java/foundation/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>
|
||||
82
java/foundation/nbproject/project.properties
Normal file
82
java/foundation/nbproject/project.properties
Normal file
@@ -0,0 +1,82 @@
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.run.all.processors=true
|
||||
application.args=
|
||||
application.title=Foundation
|
||||
application.vendor=flangner
|
||||
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
|
||||
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}/Foundation.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
file.reference.bcprov-jdk16-139.jar=lib/bcprov-jdk16-139.jar
|
||||
file.reference.cdaclient.jar=lib/cdaclient.jar
|
||||
file.reference.junit-4.11.jar=../lib/test/junit-4.11.jar
|
||||
file.reference.config.jar=lib/config.jar
|
||||
file.reference.je-3.2.13.jar=lib/je-3.2.13.jar
|
||||
file.reference.protobuf-java-2.5.0.jar=../lib/protobuf-java-2.5.0.jar
|
||||
file.reference.xbean.jar=lib/xbean.jar
|
||||
file.reference.commons-codec-1.3.jar=../lib/commons-codec-1.3.jar
|
||||
includes=**
|
||||
jar.compress=true
|
||||
javac.classpath=\
|
||||
${file.reference.commons-codec-1.3.jar}:\
|
||||
${file.reference.protobuf-java-2.5.0.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=
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
jnlp.codebase.type=local
|
||||
jnlp.enabled=false
|
||||
jnlp.offline-allowed=false
|
||||
jnlp.signed=false
|
||||
main.class=
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=false
|
||||
platform.active=default_platform
|
||||
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}
|
||||
src.dir=src
|
||||
test.src.dir=test
|
||||
22
java/foundation/nbproject/project.xml
Normal file
22
java/foundation/nbproject/project.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<buildExtensions xmlns="http://www.netbeans.org/ns/ant-build-extender/1">
|
||||
<extension file="protobuf-build.xml" id="protobuf">
|
||||
<dependency dependsOn="protobuf-code-generation" target="-pre-pre-compile"/>
|
||||
</extension>
|
||||
</buildExtensions>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>XtreemFS-foundation</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<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"/>
|
||||
</configuration>
|
||||
</project>
|
||||
154
java/foundation/src/org/xtreemfs/foundation/ClientLease.java
Normal file
154
java/foundation/src/org/xtreemfs/foundation/ClientLease.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2010 by Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public final class ClientLease implements Cloneable {
|
||||
|
||||
/**
|
||||
* Default time span for the client lease validity.
|
||||
* Must be smaller than a intra-OSD lease, if replication is
|
||||
* active!
|
||||
*/
|
||||
public static final long LEASE_VALIDITY = 15000;
|
||||
|
||||
/**
|
||||
* Indicates that a lease spans to EOF "append lease".
|
||||
* a lease from 0 to -1 spans the whole file, even if data is appended.
|
||||
*/
|
||||
public static final long TO_EOF = -1;
|
||||
|
||||
/**
|
||||
* timestamp when the lease expires
|
||||
*/
|
||||
private long firstObject;
|
||||
/**
|
||||
* last object the lease is valid for
|
||||
*/
|
||||
private long lastObject;
|
||||
|
||||
/**
|
||||
* UUID of the client owning the lease
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* timestamp when the lease expires (in seconds since 01/01/70)
|
||||
* must be XtreemFS global time!
|
||||
*/
|
||||
private long expires;
|
||||
|
||||
|
||||
/**
|
||||
* fileId this lease was issued for
|
||||
*/
|
||||
private final String fileId;
|
||||
|
||||
/**
|
||||
* sequenceNo, used to generate unique leaseId = fileId+"/"+sequenceNo
|
||||
*/
|
||||
private long sequenceNo;
|
||||
|
||||
/**
|
||||
* lease type/operation
|
||||
*/
|
||||
private String operation;
|
||||
|
||||
public static final String EXCLUSIVE_LEASE = "w";
|
||||
|
||||
|
||||
public ClientLease(final String fileId) {
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if two leases have conflicting (i.e. overlapping ranges)
|
||||
* @param other other lease for the same file
|
||||
* @return true, if there is an overlap in the ranges
|
||||
*/
|
||||
public boolean isConflicting(ClientLease other) {
|
||||
//checks
|
||||
if ( ((this.lastObject < other.firstObject) && (this.lastObject != TO_EOF)) ||
|
||||
((other.lastObject < this.firstObject) && (other.lastObject != TO_EOF)) ) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientLease clone() {
|
||||
ClientLease l = new ClientLease(this.fileId);
|
||||
l.clientId = this.clientId;
|
||||
l.expires = this.expires;
|
||||
l.firstObject = this.firstObject;
|
||||
l.lastObject = this.lastObject;
|
||||
l.operation = this.operation;
|
||||
l.sequenceNo = this.sequenceNo;
|
||||
return l;
|
||||
}
|
||||
|
||||
public long getFirstObject() {
|
||||
return firstObject;
|
||||
}
|
||||
|
||||
public void setFirstObject(long firstObject) {
|
||||
this.firstObject = firstObject;
|
||||
}
|
||||
|
||||
public long getLastObject() {
|
||||
return lastObject;
|
||||
}
|
||||
|
||||
public void setLastObject(long lastObject) {
|
||||
this.lastObject = lastObject;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public long getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
public void setExpires(long expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
|
||||
public String getFileId() {
|
||||
return fileId;
|
||||
}
|
||||
|
||||
public long getSequenceNo() {
|
||||
return sequenceNo;
|
||||
}
|
||||
|
||||
public void setSequenceNo(long sequenceNo) {
|
||||
this.sequenceNo = sequenceNo;
|
||||
}
|
||||
|
||||
public String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setOperation(String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
102
java/foundation/src/org/xtreemfs/foundation/CrashReporter.java
Normal file
102
java/foundation/src/org/xtreemfs/foundation/CrashReporter.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2010 by Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class CrashReporter {
|
||||
|
||||
public static void reportXtreemFSCrash(String report) {
|
||||
/*try {
|
||||
URL u = new URL("http://www.xtreemfs.org/dump/dump.php?srv=server");
|
||||
HttpURLConnection con = (HttpURLConnection) u.openConnection();
|
||||
con.setRequestMethod("PUT");
|
||||
con.setDoOutput(true);
|
||||
con.connect();
|
||||
OutputStream os = con.getOutputStream();
|
||||
os.write(report.getBytes());
|
||||
os.flush();
|
||||
os.close();
|
||||
|
||||
InputStream is = con.getInputStream();
|
||||
is.available();
|
||||
is.close();
|
||||
} catch (Throwable th) {
|
||||
System.out.println("cannot send crash report: "+th);
|
||||
}*/
|
||||
}
|
||||
|
||||
public static String createCrashReport(String service, String version, Throwable cause) {
|
||||
try {
|
||||
StringBuilder report = new StringBuilder();
|
||||
report.append("----------------------------------------------------------------\n");
|
||||
report.append("We are sorry, but your "+service+" has crashed. To report this bug\n");
|
||||
report.append("please go to http://www.xtreemfs.org and file an issue and attach\n");
|
||||
report.append("this crash report.\n\n");
|
||||
report.append("service: ");
|
||||
report.append(service);
|
||||
report.append(" version: ");
|
||||
report.append(version);
|
||||
report.append("\n");
|
||||
report.append("JVM version: ");
|
||||
report.append(System.getProperty("java.version"));
|
||||
report.append(" ");
|
||||
report.append(System.getProperty("java.vendor"));
|
||||
report.append(" on ");
|
||||
report.append(System.getProperty("os.name"));
|
||||
report.append(" ");
|
||||
report.append(System.getProperty("os.version"));
|
||||
report.append("\n");
|
||||
report.append("exception: ");
|
||||
report.append(cause.toString());
|
||||
report.append("\n");
|
||||
for (StackTraceElement elem : cause.getStackTrace()) {
|
||||
report.append(elem.toString());
|
||||
report.append("\n");
|
||||
}
|
||||
if (cause.getCause() != null) {
|
||||
report.append("\nroot cause: ");
|
||||
report.append(cause.getCause());
|
||||
report.append("\n");
|
||||
for (StackTraceElement elem : cause.getCause().getStackTrace()) {
|
||||
report.append(elem.toString());
|
||||
report.append("\n");
|
||||
}
|
||||
}
|
||||
reportThreadStates(report);
|
||||
|
||||
report.append("----------------------------------------------------------------\n");
|
||||
return report.toString();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return "Could not write crash report for: "+service+","+version+","+cause+" due to "+ex;
|
||||
}
|
||||
}
|
||||
|
||||
/** Logs the stack trace of each thread into {@code report}. */
|
||||
public static void reportThreadStates(StringBuilder report) {
|
||||
report.append("\n--- THREAD STATES ---\n");
|
||||
final Map<Thread,StackTraceElement[]> traces = Thread.getAllStackTraces();
|
||||
for (Thread t : traces.keySet()) {
|
||||
report.append("thread: ");
|
||||
report.append(t.getName());
|
||||
report.append("\n");
|
||||
for (StackTraceElement e : traces.get(t)) {
|
||||
report.append(e.toString());
|
||||
report.append("\n");
|
||||
}
|
||||
report.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
33
java/foundation/src/org/xtreemfs/foundation/LRUCache.java
Normal file
33
java/foundation/src/org/xtreemfs/foundation/LRUCache.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Jan Stender, Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class implements a LRU cache
|
||||
*
|
||||
* @author jmalo
|
||||
*/
|
||||
public class LRUCache<K,V> extends LinkedHashMap<K,V> {
|
||||
private static final long serialVersionUID = -4673214355284364245L;
|
||||
private int maximumSize;
|
||||
|
||||
/** Creates a new instance of LRUCache */
|
||||
public LRUCache(int size) {
|
||||
super(size, (float)0.75, true);
|
||||
|
||||
maximumSize = size;
|
||||
}
|
||||
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() > maximumSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2010 by Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
/**
|
||||
* Notifies a process of a life cycle event.
|
||||
*
|
||||
* @author stender
|
||||
*
|
||||
*/
|
||||
public interface LifeCycleListener {
|
||||
|
||||
public void startupPerformed();
|
||||
|
||||
public void shutdownPerformed();
|
||||
|
||||
public void crashPerformed(Throwable cause);
|
||||
|
||||
}
|
||||
167
java/foundation/src/org/xtreemfs/foundation/LifeCycleThread.java
Normal file
167
java/foundation/src/org/xtreemfs/foundation/LifeCycleThread.java
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
import org.xtreemfs.foundation.logging.Logging;
|
||||
import org.xtreemfs.foundation.logging.Logging.Category;
|
||||
|
||||
/**
|
||||
* A base class for threads representing a life cycle. It offers methods for
|
||||
* blocking other threads until a certain life cycle event has occurred. It
|
||||
* currently supports two life cycle-related events: startup and shutdown.
|
||||
*
|
||||
* @author stender
|
||||
*
|
||||
*/
|
||||
public class LifeCycleThread extends Thread {
|
||||
|
||||
private final Object startLock;
|
||||
|
||||
private final Object stopLock;
|
||||
|
||||
private boolean started;
|
||||
|
||||
private boolean stopped;
|
||||
|
||||
private Exception exc;
|
||||
|
||||
private LifeCycleListener listener;
|
||||
|
||||
public LifeCycleThread(String name) {
|
||||
super(name);
|
||||
startLock = new Object();
|
||||
stopLock = new Object();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be invoked by subclasses when the startup procedure
|
||||
* has been completed.
|
||||
*/
|
||||
protected void notifyStarted() {
|
||||
|
||||
if (Logging.isInfo())
|
||||
Logging.logMessage(Logging.LEVEL_INFO, Category.lifecycle, this, "Thread %s started", Thread
|
||||
.currentThread().getName());
|
||||
|
||||
synchronized (startLock) {
|
||||
started = true;
|
||||
startLock.notifyAll();
|
||||
if (listener != null)
|
||||
listener.startupPerformed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be invoked by subclasses when the shutdown procedure
|
||||
* has been completed.
|
||||
*/
|
||||
protected void notifyStopped() {
|
||||
|
||||
if (Logging.isInfo())
|
||||
Logging.logMessage(Logging.LEVEL_INFO, Category.lifecycle, this, "Thread %s terminated", Thread
|
||||
.currentThread().getName());
|
||||
|
||||
synchronized (stopLock) {
|
||||
stopped = true;
|
||||
stopLock.notifyAll();
|
||||
if (listener != null)
|
||||
listener.shutdownPerformed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be invoked by subclasses when the thread has crashed.
|
||||
*/
|
||||
protected void notifyCrashed(Throwable exc) {
|
||||
|
||||
Logging.logMessage(Logging.LEVEL_CRIT, this, "service ***CRASHED***, shutting down");
|
||||
Logging.logError(Logging.LEVEL_CRIT, this, exc);
|
||||
|
||||
synchronized (startLock) {
|
||||
this.exc = exc instanceof Exception ? (Exception) exc : new Exception(exc);
|
||||
started = true;
|
||||
startLock.notifyAll();
|
||||
}
|
||||
|
||||
synchronized (stopLock) {
|
||||
this.exc = exc instanceof Exception ? (Exception) exc : new Exception(exc);
|
||||
stopped = true;
|
||||
stopLock.notifyAll();
|
||||
}
|
||||
|
||||
if (listener != null)
|
||||
listener.crashPerformed(exc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously waits for a notification indicating that the startup
|
||||
* procedure has been completed.
|
||||
*
|
||||
* @throws Exception
|
||||
* if an error occurred during the startup procedure
|
||||
*/
|
||||
public void waitForStartup() throws Exception {
|
||||
synchronized (startLock) {
|
||||
|
||||
while (!started)
|
||||
startLock.wait();
|
||||
|
||||
if (exc != null && listener == null)
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously waits for a notification indicating that the shutdown
|
||||
* procedure has been completed.
|
||||
*
|
||||
* @throws Exception
|
||||
* if an error occurred during the shutdown procedure
|
||||
*/
|
||||
public void waitForShutdown() throws Exception {
|
||||
synchronized (stopLock) {
|
||||
|
||||
if (!started)
|
||||
return;
|
||||
while (!stopped)
|
||||
try {
|
||||
stopLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// In case this thread executes notifyCrashed(), he will
|
||||
// probably interrupt itself. However, this should not
|
||||
// interfere with the notifyCrashed() procedure and
|
||||
// therefore we swallow this exception.
|
||||
if (listener == null) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (exc != null && listener == null)
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the thread. This method should be overridden in subclasses.
|
||||
* @throws Exception if an error occurred
|
||||
*/
|
||||
public void shutdown() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener waiting for life cycle events.
|
||||
*
|
||||
* @param listener
|
||||
* the listener
|
||||
*/
|
||||
public void setLifeCycleListener(LifeCycleListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
}
|
||||
407
java/foundation/src/org/xtreemfs/foundation/SSLOptions.java
Normal file
407
java/foundation/src/org/xtreemfs/foundation/SSLOptions.java
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender, Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Security;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.xtreemfs.foundation.logging.Logging;
|
||||
import org.xtreemfs.foundation.logging.Logging.Category;
|
||||
import org.xtreemfs.foundation.util.OutputUtils;
|
||||
|
||||
/**
|
||||
* Encapsulates the SSLOptions for the connections of pinky and speedy
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public class SSLOptions {
|
||||
/**
|
||||
* a Java JKS Keystore
|
||||
*/
|
||||
public final static String JKS_CONTAINER = "JKS";
|
||||
|
||||
/**
|
||||
* a PKCS12 Keystore
|
||||
*/
|
||||
public final static String PKCS12_CONTAINER = "PKCS12";
|
||||
|
||||
/**
|
||||
* Default SSL/TLS Protocol to use when no or an invalid protocol was specified
|
||||
*/
|
||||
public final static String DEFAULT_SSL_PROTOCOL = "TLS";
|
||||
|
||||
/**
|
||||
* file with the private key and the public cert for the server
|
||||
*/
|
||||
private final InputStream serverCredentialFile;
|
||||
|
||||
/**
|
||||
* file with trusted public certs
|
||||
*/
|
||||
private final InputStream trustedCertificatesFile;
|
||||
|
||||
/**
|
||||
* passphrase of the server credential file
|
||||
*/
|
||||
private final char[] serverCredentialFilePassphrase;
|
||||
|
||||
/**
|
||||
* passphrase of the trusted certificates file
|
||||
*/
|
||||
private final char[] trustedCertificatesFilePassphrase;
|
||||
|
||||
/**
|
||||
* using symmetric encryption or only authenticating via certs
|
||||
*/
|
||||
private boolean authenticationWithoutEncryption;
|
||||
|
||||
/**
|
||||
* file format of the server credential file
|
||||
*/
|
||||
private final String serverCredentialFileContainer;
|
||||
|
||||
/**
|
||||
* file format of the trusted certificates file
|
||||
*/
|
||||
private final String trustedCertificatesFileContainer;
|
||||
|
||||
/**
|
||||
* knows the used certs and more
|
||||
*/
|
||||
private final SSLContext sslContext;
|
||||
|
||||
private final boolean useFakeSSLMode;
|
||||
|
||||
public SSLOptions(InputStream serverCredentialFile, String serverCredentialFilePassphrase,
|
||||
String serverCredentialFileContainer, InputStream trustedCertificatesFile,
|
||||
String trustedCertificatesFilePassphrase, String trustedCertificatesFileContainer,
|
||||
boolean authenticationWithoutEncryption, boolean useFakeSSLMode, String sslProtocolString,
|
||||
TrustManager trustManager) throws IOException {
|
||||
|
||||
this.serverCredentialFile = serverCredentialFile;
|
||||
this.trustedCertificatesFile = trustedCertificatesFile;
|
||||
|
||||
if (serverCredentialFilePassphrase != null)
|
||||
this.serverCredentialFilePassphrase = serverCredentialFilePassphrase.toCharArray();
|
||||
else
|
||||
this.serverCredentialFilePassphrase = null;
|
||||
|
||||
if (trustedCertificatesFilePassphrase != null)
|
||||
this.trustedCertificatesFilePassphrase = trustedCertificatesFilePassphrase.toCharArray();
|
||||
else
|
||||
this.trustedCertificatesFilePassphrase = null;
|
||||
|
||||
this.serverCredentialFileContainer = serverCredentialFileContainer;
|
||||
this.trustedCertificatesFileContainer = trustedCertificatesFileContainer;
|
||||
|
||||
this.authenticationWithoutEncryption = authenticationWithoutEncryption;
|
||||
|
||||
this.useFakeSSLMode = useFakeSSLMode;
|
||||
|
||||
sslContext = createSSLContext(sslProtocolStringToProtocol(sslProtocolString), trustManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create/initialize the SSLContext with key material
|
||||
*
|
||||
* @param trustManager
|
||||
* the trust manager for the SSL context (may be
|
||||
* <code>null</code>)
|
||||
* @return the created and initialized SSLContext
|
||||
* @throws IOException
|
||||
*/
|
||||
private SSLContext createSSLContext(String sslProtocol, TrustManager trustManager) throws IOException {
|
||||
SSLContext sslContext = null;
|
||||
try {
|
||||
// First initialize the key and trust material.
|
||||
KeyStore ksKeys = KeyStore.getInstance(serverCredentialFileContainer);
|
||||
ksKeys.load(serverCredentialFile, serverCredentialFilePassphrase);
|
||||
|
||||
// KeyManager's decide which key material to use.
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(ksKeys, serverCredentialFilePassphrase);
|
||||
|
||||
// There are quite a few issues with the OpenJDK PKCS11 provider in combination with NSS,
|
||||
// so remove it no matter what the OpenJDK version is.
|
||||
if ("OpenJDK Runtime Environment".equals(System.getProperty("java.runtime.name"))) {
|
||||
try {
|
||||
Security.removeProvider("SunPKCS11-NSS");
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "Successfully removed faulty security provider 'SunPKCS11-NSS'.");
|
||||
}
|
||||
} catch(SecurityException e) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this,
|
||||
"Could not remove security provider 'SunPKCS11-NSS'. This might cause TLS connections to time out. " +
|
||||
"Known to affect multiple OpenJDK / NSS version combinations.");
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "%s:\n%s", e.getMessage(), OutputUtils.stackTraceToString(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Re-enable disabled algorithms if the user requests it.
|
||||
final String defaultDisabledAlgorithms = Security.getProperty("jdk.tls.disabledAlgorithms");
|
||||
removeDisabledEntailedProtocolSupportForProtocol(sslProtocol);
|
||||
|
||||
try {
|
||||
sslContext = SSLContext.getInstance(sslProtocol);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this, "Unsupported algorithm '%s', defaulting to '%s'.",
|
||||
sslProtocol, DEFAULT_SSL_PROTOCOL);
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "%s:\n%s", e.getMessage(), OutputUtils.stackTraceToString(e));
|
||||
}
|
||||
|
||||
// Reset disabled algorithms because the context could not be created.
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "Trying to reset disabled algorithms.");
|
||||
}
|
||||
try {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", defaultDisabledAlgorithms);
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "Successfully reset disabled algorithms.");
|
||||
}
|
||||
} catch (SecurityException e1) {
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "Could not reset disabled algorithms: %s", OutputUtils.stackTraceToString(e1));
|
||||
}
|
||||
}
|
||||
|
||||
// Setup everything anew for the default SSL protocol.
|
||||
removeDisabledEntailedProtocolSupportForProtocol(DEFAULT_SSL_PROTOCOL);
|
||||
sslContext = SSLContext.getInstance(DEFAULT_SSL_PROTOCOL);
|
||||
}
|
||||
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "Disabling the following algorithms: %s", Security.getProperty("jdk.tls.disabledAlgorithms"));
|
||||
}
|
||||
|
||||
if (trustManager != null) {
|
||||
// if a user-defined trust manager is set ...
|
||||
trustManager.init(trustedCertificatesFileContainer, trustedCertificatesFile,
|
||||
trustedCertificatesFilePassphrase);
|
||||
sslContext.init(kmf.getKeyManagers(), new TrustManager[] { trustManager }, null);
|
||||
} else if (trustedCertificatesFileContainer.equals("none")) {
|
||||
TrustManager[] myTMs = new TrustManager[] { new NoAuthTrustStore() };
|
||||
sslContext.init(kmf.getKeyManagers(), myTMs, null);
|
||||
} else {
|
||||
|
||||
// TrustManager's decide whether to allow connections.
|
||||
KeyStore ksTrust = null;
|
||||
if (trustedCertificatesFileContainer.equals("none")) {
|
||||
ksTrust = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
} else {
|
||||
ksTrust = KeyStore.getInstance(trustedCertificatesFileContainer);
|
||||
ksTrust.load(trustedCertificatesFile, trustedCertificatesFilePassphrase);
|
||||
}
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ksTrust);
|
||||
|
||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
}
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
public boolean isAuthenticationWithoutEncryption() {
|
||||
return this.authenticationWithoutEncryption;
|
||||
}
|
||||
|
||||
public void setAuthenticationWithoutEncryption(boolean authenticationWithoutEncryption) {
|
||||
this.authenticationWithoutEncryption = authenticationWithoutEncryption;
|
||||
}
|
||||
|
||||
public InputStream getServerCredentialFile() {
|
||||
return this.serverCredentialFile;
|
||||
}
|
||||
|
||||
public String getServerCredentialFileContainer() {
|
||||
return this.serverCredentialFileContainer;
|
||||
}
|
||||
|
||||
public String getServerCredentialFilePassphrase() {
|
||||
return this.serverCredentialFilePassphrase.toString();
|
||||
}
|
||||
|
||||
public InputStream getTrustedCertificatesFile() {
|
||||
return this.trustedCertificatesFile;
|
||||
}
|
||||
|
||||
public String getTrustedCertificatesFileContainer() {
|
||||
return this.trustedCertificatesFileContainer;
|
||||
}
|
||||
|
||||
public String getTrustedCertificatesFilePassphrase() {
|
||||
return this.trustedCertificatesFilePassphrase.toString();
|
||||
}
|
||||
|
||||
public SSLContext getSSLContext() {
|
||||
return this.sslContext;
|
||||
}
|
||||
|
||||
public boolean isFakeSSLMode() {
|
||||
return this.useFakeSSLMode;
|
||||
}
|
||||
|
||||
public String getSSLProtocol() {
|
||||
return sslContext.getProtocol();
|
||||
}
|
||||
|
||||
public boolean isSSLEngineProtocolSupported(String sslEngineProtocol) {
|
||||
// Protocol names in JDK 5, 6: SSLv2Hello, SSLv3, TLSv1
|
||||
// Additionally in JDK 7, 8: TLSv1.2
|
||||
// TLSv1.1 seems to depend on the vendor
|
||||
String sslProtocol = getSSLProtocol();
|
||||
if ("SSLv3".equals(sslProtocol)) {
|
||||
return "SSLv3".equals(sslEngineProtocol);
|
||||
} else if ("TLS".equals(sslProtocol)) {
|
||||
return "SSLv3".equals(sslEngineProtocol) ||
|
||||
"TLSv1".equals(sslEngineProtocol) ||
|
||||
"TLSv1.1".equals(sslEngineProtocol) ||
|
||||
"TLSv1.2".equals(sslEngineProtocol);
|
||||
} else if ("TLSv1".equals(sslProtocol)) {
|
||||
return "TLSv1".equals(sslEngineProtocol);
|
||||
} else if ("TLSv1.1".equals(sslProtocol)) {
|
||||
return "TLSv1.1".equals(sslEngineProtocol);
|
||||
} else if ("TLSv1.2".equals(sslProtocol)) {
|
||||
return "TLSv1.2".equals(sslEngineProtocol);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String sslProtocolStringToProtocol(String sslProtocolString) {
|
||||
// SSL Context Protocol Strings:
|
||||
// JDK 6: SSL, SSLv2, SSLv3, TLS, TLSv1
|
||||
// additionally in JDK 7: TLSv1.2
|
||||
// TLSv1.1 seems to depend on the vendor
|
||||
if ("sslv3".equals(sslProtocolString)) {
|
||||
return "SSLv3";
|
||||
} else if ("ssltls".equals(sslProtocolString)) {
|
||||
return "TLS";
|
||||
} else if ("tlsv1".equals(sslProtocolString)) {
|
||||
return "TLSv1";
|
||||
} else if ("tlsv11".equals(sslProtocolString)) {
|
||||
return "TLSv1.1";
|
||||
} else if ("tlsv12".equals(sslProtocolString)) {
|
||||
return "TLSv1.2";
|
||||
} else {
|
||||
if (sslProtocolString != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.net, this,
|
||||
"Unknown SSL Context Protocol: '%s', defaulting to '%s'.",
|
||||
sslProtocolString, DEFAULT_SSL_PROTOCOL);
|
||||
}
|
||||
return DEFAULT_SSL_PROTOCOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all protocols that should be supported when using {@code sslProtocol} from the disabled
|
||||
* algorithms list that is set as system default, e.g. in /usr/lib/jvm/default-java/jre/lib/security/java.security.
|
||||
*
|
||||
* @param sslProtocol
|
||||
*/
|
||||
private void removeDisabledEntailedProtocolSupportForProtocol(String sslProtocol) {
|
||||
if (Security.getProperty("jdk.tls.disabledAlgorithms") == null) {
|
||||
return; // no disabled algorithms, everything is allowed by default
|
||||
}
|
||||
|
||||
String[] entailedSupportedProtocols = new String[] {};
|
||||
if ("SSLv3".equals(sslProtocol)) {
|
||||
entailedSupportedProtocols = new String[] { "SSLv3" };
|
||||
} else if ("TLS".equals(sslProtocol)) {
|
||||
entailedSupportedProtocols = new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" };
|
||||
} else if ("TLSv1".equals(sslProtocol)) {
|
||||
entailedSupportedProtocols = new String[] { "TLSv1" };
|
||||
} else if ("TLSv1.1".equals(sslProtocol)) {
|
||||
entailedSupportedProtocols = new String[] { "TLSv1.1" };
|
||||
} else if ("TLSv1.2".equals(sslProtocol)) {
|
||||
entailedSupportedProtocols = new String[] { "TLSv1.2" };
|
||||
}
|
||||
|
||||
// For each protocol whose support is entailed by the requested protocol,
|
||||
// remove it from the disabled algorithms list if possible.
|
||||
for (String supportedSSLProtocol : entailedSupportedProtocols) {
|
||||
if (Security.getProperty("jdk.tls.disabledAlgorithms").contains(supportedSSLProtocol)) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this,
|
||||
"Algorithm '%s' is disabled in your java.security configuration file (see key 'jdk.tls.disabledAlgorithms'). " +
|
||||
"Trying to enable algorithm '%s' manually as specified in your configuration file (see key 'ssl.protocol'). " +
|
||||
"Consider using a newer SSL/TLS algorithm for your setup, " +
|
||||
"as algorithm '%s' has been disabled by default because of security issues.",
|
||||
supportedSSLProtocol, supportedSSLProtocol, supportedSSLProtocol);
|
||||
try {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms",
|
||||
Security.getProperty("jdk.tls.disabledAlgorithms").replace(supportedSSLProtocol, "").replace(" ", ""));
|
||||
if (Logging.isDebug()) {
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this, "Successfully removed algorithm '%s' from disabled algorithms.",
|
||||
supportedSSLProtocol);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this, "Could not remove algorithm '%s' from disabled algorithm. " +
|
||||
"This might cause SSL Handshake exceptions. For SSLv3 this is known to affect all JDKs fixing issue CVE-2014-3566.",
|
||||
supportedSSLProtocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoAuthTrustStore implements TrustManager, X509TrustManager {
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(String trustedCertificatesFileContainer, InputStream trustedCertificatesFile,
|
||||
char[] trustedCertificatesFilePassphrase) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static interface TrustManager extends javax.net.ssl.TrustManager {
|
||||
public void init(String trustedCertificatesFileContainer, InputStream trustedCertificatesFile,
|
||||
char[] trustedCertificatesFilePassphrase);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2010 by Felix Langner,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import org.xtreemfs.foundation.pbrpc.client.RPCResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Provides methods to synchronize with a XtreemFS TimeServer, usually provided
|
||||
* by a DIR service.
|
||||
*
|
||||
* @author flangner
|
||||
* @since 03/01/2010
|
||||
*/
|
||||
|
||||
public interface TimeServerClient {
|
||||
|
||||
/**
|
||||
* Requests the global time at the given server.
|
||||
*
|
||||
* @param server - if null, the default will be used.
|
||||
* @return a {@link RPCResponse} future for an UNIX time-stamp.
|
||||
*/
|
||||
public long xtreemfs_global_time_get(InetSocketAddress server);
|
||||
}
|
||||
464
java/foundation/src/org/xtreemfs/foundation/TimeSync.java
Normal file
464
java/foundation/src/org/xtreemfs/foundation/TimeSync.java
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Jan Stender, Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.xtreemfs.foundation.logging.Logging;
|
||||
import org.xtreemfs.foundation.logging.Logging.Category;
|
||||
|
||||
/**
|
||||
* A class that offers a local time w/ adjustable granularity and a global time
|
||||
* based on the time reported by the DIR. Global time is adjusted periodically.
|
||||
* This class should be used to minimize the number of calls to
|
||||
* System.currentTimeMillis which is a costly system call on Linux. Moreover it
|
||||
* offers a system-global time.
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public final class TimeSync extends LifeCycleThread {
|
||||
|
||||
public enum ExtSyncSource {
|
||||
XTREEMFS_DIR, GPSD, LOCAL_CLOCK
|
||||
};
|
||||
|
||||
/**
|
||||
* The maximum round trip time for a clock synchronization message between
|
||||
* the <code>TimeSync</code> and the DIR. If the round trip time of a
|
||||
* synchronization message exceeds this value, the message will be ignored.
|
||||
*/
|
||||
private static final int MAX_RTT = 1000;
|
||||
|
||||
/**
|
||||
* A client used to synchronize clocks
|
||||
*/
|
||||
private TimeServerClient timeServerClient;
|
||||
|
||||
/**
|
||||
* interval in ms to wait between to synchronizations.
|
||||
*/
|
||||
private volatile int timeSyncInterval;
|
||||
|
||||
/**
|
||||
* interval between updates of the local system clock.
|
||||
*
|
||||
* If it's set to 0, the local renew by the thread is disabled and the time
|
||||
* is read from the system on demand.
|
||||
*/
|
||||
private volatile int localTimeRenew;
|
||||
|
||||
private volatile ExtSyncSource syncSource;
|
||||
|
||||
private InetSocketAddress gpsdAddr;
|
||||
|
||||
/**
|
||||
* local sys time as of last update
|
||||
*/
|
||||
private volatile long localSysTime;
|
||||
|
||||
/**
|
||||
* drift between local clock and global time as of last resync() operation.
|
||||
*/
|
||||
private volatile long currentDrift;
|
||||
|
||||
/**
|
||||
* set to true to stop thread
|
||||
*/
|
||||
private volatile boolean quit;
|
||||
|
||||
/**
|
||||
* timestamp of last resync operation
|
||||
*/
|
||||
private volatile long lastSuccessfulSync;
|
||||
|
||||
/**
|
||||
* Timestamp of the last resync attempt.
|
||||
*
|
||||
* @note No need to specify it as volatile since it's only used by run().
|
||||
*/
|
||||
private long lastSyncAttempt;
|
||||
|
||||
private volatile int syncRTT;
|
||||
|
||||
private volatile boolean syncSuccess;
|
||||
|
||||
private static TimeSync theInstance;
|
||||
|
||||
private final Pattern gpsdDatePattern;
|
||||
|
||||
private Socket gpsdSocket;
|
||||
|
||||
/**
|
||||
* Creates a new instance of TimeSync
|
||||
*
|
||||
* @dir a directory server to use for synchronizing clocks, can be null for
|
||||
* test setups only
|
||||
*/
|
||||
private TimeSync(ExtSyncSource source, TimeServerClient dir, InetSocketAddress gpsd, int timeSyncInterval, int localTimeRenew) {
|
||||
super("TSync Thr");
|
||||
setDaemon(true);
|
||||
this.syncSuccess = false;
|
||||
this.gpsdDatePattern = Pattern.compile("GPSD,D=(....)-(..)-(..)T(..):(..):(..)\\.(.+)Z");
|
||||
|
||||
init(source, dir, gpsd, timeSyncInterval, localTimeRenew);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the TimeSync with new parameters.
|
||||
*
|
||||
* @param source
|
||||
* @param dir
|
||||
* @param gpsd
|
||||
* @param timeSyncInterval
|
||||
* @param localTimeRenew
|
||||
*/
|
||||
public synchronized void init(ExtSyncSource source, TimeServerClient dir, InetSocketAddress gpsd, int timeSyncInterval, int localTimeRenew) {
|
||||
this.localTimeRenew = localTimeRenew;
|
||||
this.timeSyncInterval = timeSyncInterval;
|
||||
this.timeServerClient = dir;
|
||||
this.syncSource = source;
|
||||
this.gpsdAddr = gpsd;
|
||||
|
||||
if (this.timeServerClient != null && this.timeSyncInterval != 0 && this.localTimeRenew != 0) {
|
||||
this.localTimeRenew = 0;
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this,
|
||||
"Disabled the periodic local time renew (set local_clock_renewal to 0)" +
|
||||
" and using always the current system time as base since the time will be corrected by synchronizing with the DIR service.");
|
||||
}
|
||||
|
||||
if (source == ExtSyncSource.GPSD) {
|
||||
try {
|
||||
if (gpsdSocket != null)
|
||||
gpsdSocket.close();
|
||||
|
||||
gpsdSocket = new Socket();
|
||||
gpsdSocket.setSoTimeout(2000);
|
||||
gpsdSocket.setTcpNoDelay(true);
|
||||
gpsdSocket.connect(gpsdAddr,2000);
|
||||
} catch (IOException ex) {
|
||||
Logging.logMessage(Logging.LEVEL_ERROR, this,"cannot connect to GPSd: "+ex);
|
||||
gpsdSocket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* main loop
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
TimeSync.theInstance = this;
|
||||
notifyStarted();
|
||||
String tsStatus;
|
||||
if (localTimeRenew == 0) {
|
||||
tsStatus = "using the local clock";
|
||||
} else {
|
||||
tsStatus = "using the local clock (precision is " + this.localTimeRenew + " ms)";
|
||||
}
|
||||
if (this.timeServerClient != null && timeSyncInterval != 0) {
|
||||
tsStatus += " and remote sync every " + this.timeSyncInterval + " ms";
|
||||
}
|
||||
Logging.logMessage(Logging.LEVEL_INFO, Category.lifecycle, this, "TimeSync is running %s", tsStatus);
|
||||
while (!quit) {
|
||||
// Renew cached local time.
|
||||
final long previousLocalSysTime = localSysTime;
|
||||
localSysTime = System.currentTimeMillis();
|
||||
if (localTimeRenew > 0 && previousLocalSysTime != 0) {
|
||||
final long timeBetweenUpdates = Math.abs(localSysTime - previousLocalSysTime);
|
||||
if (timeBetweenUpdates > 4 * localTimeRenew) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this,
|
||||
"The granularity of the renewed local time could not be guaranteed" +
|
||||
" since it took longer to retrieve the latest local time (%d ms) than configured (local_clock_renewal = %d)." +
|
||||
" Maybe the system is under high I/O load and therefore scheduling threads takes longer than usual?",
|
||||
timeBetweenUpdates,
|
||||
localTimeRenew);
|
||||
}
|
||||
}
|
||||
|
||||
// Remote sync time.
|
||||
if (timeSyncInterval != 0 && localSysTime - lastSyncAttempt > timeSyncInterval) {
|
||||
resync();
|
||||
}
|
||||
if (!quit) {
|
||||
//
|
||||
try {
|
||||
// If local refresh was disabled, use timeSyncInterval as sleep time.
|
||||
long sleepTimeMs = localTimeRenew != 0 ? localTimeRenew : timeSyncInterval;
|
||||
if (sleepTimeMs == 0) {
|
||||
// If there is no need to run this thread at all, let it sleep for 10 minutes.
|
||||
sleepTimeMs = 600000;
|
||||
}
|
||||
TimeSync.sleep(sleepTimeMs);
|
||||
} catch (InterruptedException ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
notifyStopped();
|
||||
syncSuccess = false;
|
||||
theInstance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the time synchronizer. Note that only the first invocation of
|
||||
* this method has an effect, any further invocations will be ignored.
|
||||
*
|
||||
* @param dir
|
||||
* @param timeSyncInterval
|
||||
* @param localTimeRenew
|
||||
* @param dirAuthStr
|
||||
*/
|
||||
public static TimeSync initialize(TimeServerClient dir, int timeSyncInterval, int localTimeRenew) throws Exception {
|
||||
|
||||
if (theInstance != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.lifecycle, null, "time sync already running",
|
||||
new Object[0]);
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
TimeSync s = new TimeSync(ExtSyncSource.XTREEMFS_DIR, dir, null, timeSyncInterval, localTimeRenew);
|
||||
s.start();
|
||||
s.waitForStartup();
|
||||
return s;
|
||||
}
|
||||
|
||||
public static TimeSync initializeLocal(int localTimeRenew) {
|
||||
if (theInstance != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.lifecycle, null, "time sync already running",
|
||||
new Object[0]);
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
TimeSync s = new TimeSync(ExtSyncSource.LOCAL_CLOCK, null, null, 0, localTimeRenew);
|
||||
s.start();
|
||||
return s;
|
||||
}
|
||||
|
||||
public static TimeSync initializeGPSD(InetSocketAddress gpsd, int timeSyncInterval, int localTimeRenew) {
|
||||
if (theInstance != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.lifecycle, null, "time sync already running",
|
||||
new Object[0]);
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
TimeSync s = new TimeSync(ExtSyncSource.GPSD, null, gpsd, timeSyncInterval, localTimeRenew);
|
||||
s.start();
|
||||
return s;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
shutdown();
|
||||
try {
|
||||
waitForShutdown();
|
||||
} catch (Exception e) {
|
||||
Logging.logError(Logging.LEVEL_ERROR, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stop the thread
|
||||
*/
|
||||
public void shutdown() {
|
||||
quit = true;
|
||||
this.interrupt();
|
||||
if (gpsdSocket != null) {
|
||||
try {
|
||||
gpsdSocket.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current value of the local system time variable. Has a
|
||||
* resolution of localTimeRenew ms.
|
||||
*/
|
||||
public static long getLocalSystemTime() {
|
||||
TimeSync ts = getInstance();
|
||||
if (ts.localTimeRenew == 0 || ts.localSysTime == 0) {
|
||||
return System.currentTimeMillis();
|
||||
} else {
|
||||
return ts.localSysTime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current value of the local system time adjusted to global
|
||||
* time. Has a resolution of localTimeRenew ms.
|
||||
*/
|
||||
public static long getGlobalTime() {
|
||||
TimeSync ts = getInstance();
|
||||
if (ts.localTimeRenew == 0 || ts.localSysTime == 0) {
|
||||
return System.currentTimeMillis() + ts.currentDrift;
|
||||
} else {
|
||||
return ts.localSysTime + ts.currentDrift;
|
||||
}
|
||||
}
|
||||
|
||||
public static long getLocalRenewInterval() {
|
||||
return getInstance().localTimeRenew;
|
||||
}
|
||||
|
||||
public static int getTimeSyncInterval() {
|
||||
return getInstance().timeSyncInterval;
|
||||
}
|
||||
|
||||
public static int getSyncRTT() {
|
||||
return getInstance().syncRTT;
|
||||
}
|
||||
|
||||
public static boolean lastSyncWasSuccessful() {
|
||||
return getInstance().syncSuccess;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the timestamp (local time) when the drift
|
||||
* was successfully calculated
|
||||
*/
|
||||
public static long getLastSuccessfulSyncTimestamp() {
|
||||
return getInstance().lastSuccessfulSync;
|
||||
}
|
||||
/**
|
||||
* returns the current clock drift.
|
||||
*/
|
||||
public long getDrift() {
|
||||
return this.currentDrift;
|
||||
}
|
||||
|
||||
/**
|
||||
* resynchronizes with the global time obtained from the DIR
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void resync() {
|
||||
switch (syncSource) {
|
||||
case LOCAL_CLOCK : return;
|
||||
case XTREEMFS_DIR : {
|
||||
try {
|
||||
long tStart = System.currentTimeMillis();
|
||||
lastSyncAttempt = tStart;
|
||||
long oldDrift = currentDrift;
|
||||
long globalTime = timeServerClient.xtreemfs_global_time_get(null);
|
||||
if (globalTime <= 0) {
|
||||
//error
|
||||
return;
|
||||
}
|
||||
|
||||
long tEnd = System.currentTimeMillis();
|
||||
// add half a roundtrip to estimate the delay
|
||||
syncRTT = (int)(tEnd - tStart);
|
||||
|
||||
if (syncRTT > MAX_RTT) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.misc, this,
|
||||
"Ignored time synchronization message because DIR took too long to respond (%d ms)",
|
||||
syncRTT);
|
||||
syncSuccess = false;
|
||||
return;
|
||||
}
|
||||
|
||||
globalTime += syncRTT / 2;
|
||||
syncSuccess = true;
|
||||
|
||||
currentDrift = globalTime - tEnd;
|
||||
lastSuccessfulSync = tEnd;
|
||||
|
||||
if (Math.abs(oldDrift - currentDrift) > 5000 && oldDrift != 0) {
|
||||
Logging.logMessage(Logging.LEVEL_ERROR, Category.misc, this,
|
||||
"STRANGE DRIFT CHANGE from %d to %d", oldDrift, currentDrift);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
syncSuccess = false;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPSD : {
|
||||
try {
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(gpsdSocket.getInputStream()));
|
||||
OutputStream os = gpsdSocket.getOutputStream();
|
||||
long tStart = System.currentTimeMillis();
|
||||
lastSyncAttempt = tStart;
|
||||
|
||||
os.write(new byte[]{'d','\n'});
|
||||
os.flush();
|
||||
|
||||
long oldDrift = currentDrift;
|
||||
String response = br.readLine();
|
||||
long tEnd = System.currentTimeMillis();
|
||||
|
||||
|
||||
Matcher m = gpsdDatePattern.matcher(response);
|
||||
Calendar c = Calendar.getInstance();
|
||||
if (m.matches()) {
|
||||
c.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
|
||||
c.set(Calendar.MONTH, Integer.parseInt(m.group(2))-1);
|
||||
c.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(3)));
|
||||
c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4)));
|
||||
c.set(Calendar.MINUTE, Integer.parseInt(m.group(5)));
|
||||
c.set(Calendar.SECOND, Integer.parseInt(m.group(6)));
|
||||
//c.set(Calendar.MILLISECOND, Integer.parseInt(m.group(7))*10);
|
||||
} else {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this,"cannot parse GPSd response: %s",response);
|
||||
syncSuccess = false;
|
||||
return;
|
||||
}
|
||||
|
||||
long globalTime = c.getTimeInMillis();
|
||||
Date d = new Date(globalTime);
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this,"global GPSd time: %d (%d:%d:%d)",c.getTimeInMillis(),d.getHours(),
|
||||
d.getMinutes(),d.getSeconds());
|
||||
|
||||
// add half a roundtrip to estimate the delay
|
||||
syncRTT = (int)(tEnd - tStart);
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, this,"sync RTT: %d ms",syncRTT);
|
||||
globalTime += syncRTT / 2;
|
||||
syncSuccess = true;
|
||||
|
||||
currentDrift = globalTime - tEnd;
|
||||
lastSuccessfulSync = tEnd;
|
||||
|
||||
Logging.logMessage(Logging.LEVEL_DEBUG, Category.misc, this,
|
||||
"resync success, drift: %d ms", Math.abs(oldDrift-currentDrift));
|
||||
|
||||
if (Math.abs(oldDrift - currentDrift) > 5000 && oldDrift != 0) {
|
||||
Logging.logMessage(Logging.LEVEL_ERROR, Category.misc, this,
|
||||
"STRANGE DRIFT CHANGE from %d to %d", oldDrift, currentDrift);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
syncSuccess = false;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static TimeSync getInstance() {
|
||||
if (theInstance == null)
|
||||
throw new RuntimeException("TimeSync not initialized!");
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return theInstance != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Jan Stender, Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation;
|
||||
|
||||
/**
|
||||
* This class is meant to maintain version numbers for different components used
|
||||
* in XtreemFS, in order to be able to detect possible incompatibilities between
|
||||
* different versions.
|
||||
*
|
||||
* When a new version of the protocol, database, etc. has been implemented, the
|
||||
* corresponding version number should be replaced. XtreemFS will rely on this
|
||||
* class to find out what the current version numbers are.
|
||||
*
|
||||
*/
|
||||
public class VersionManagement {
|
||||
|
||||
public static final String RELEASE_VERSION = "1.5.1 (Wonderful Waffles)";
|
||||
|
||||
private static final long mrcDataVersion = 10;
|
||||
|
||||
private static final long osdDataVersion = 1;
|
||||
|
||||
private static final long foundationVersion = 2;
|
||||
|
||||
public static long getMrcDataVersion() {
|
||||
return mrcDataVersion;
|
||||
}
|
||||
|
||||
public static long getOsdDataVersion() {
|
||||
return osdDataVersion;
|
||||
}
|
||||
|
||||
public static long getFoundationVersion() {
|
||||
return foundationVersion;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2010 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.buffer;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public final class ASCIIString implements Serializable {
|
||||
private static final long serialVersionUID = 4633232360908659139L;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
private int hash;
|
||||
|
||||
protected ASCIIString() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of ASCIIString
|
||||
*/
|
||||
public ASCIIString(String str) {
|
||||
this.data = str.getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of ASCIIString
|
||||
*/
|
||||
protected ASCIIString(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String(data);
|
||||
}
|
||||
|
||||
public char charAt(int index) {
|
||||
|
||||
return (char)data[index];
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
try {
|
||||
ASCIIString other = (ASCIIString)o;
|
||||
|
||||
if (other.length() != this.length())
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
if (data[i] != other.data[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (ClassCastException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void marshall(ReusableBuffer target) {
|
||||
target.putInt(data.length);
|
||||
target.put(data);
|
||||
|
||||
}
|
||||
|
||||
public static ASCIIString unmarshall(ReusableBuffer target) {
|
||||
|
||||
int length = target.getInt();
|
||||
if (length < 0)
|
||||
return null;
|
||||
byte[] tmp = new byte[length];
|
||||
|
||||
target.get(tmp);
|
||||
|
||||
return new ASCIIString(tmp);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
h = 31*h + data[i];
|
||||
}
|
||||
hash = h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
public int getSerializedSize() {
|
||||
return length()+Integer.SIZE/8;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* A concurrent pool for buffer recycling.
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public final class BufferPool {
|
||||
|
||||
/**
|
||||
* size of buffers for each class.
|
||||
*/
|
||||
public static final int[] BUFF_SIZES = { 8192, 65536, 131072, 524288,
|
||||
2097152 };
|
||||
|
||||
/**
|
||||
* max pool size for each class
|
||||
*/
|
||||
public static final int[] MAX_POOL_SIZES = { 2000, 200, 100, 10, 5 };
|
||||
|
||||
/**
|
||||
* queues to store buffers in
|
||||
*/
|
||||
private final ConcurrentLinkedQueue<ByteBuffer>[] pools;
|
||||
|
||||
/**
|
||||
* pool sizes to avoid counting elements on each access
|
||||
*/
|
||||
private final AtomicInteger[] poolSizes;
|
||||
|
||||
/**
|
||||
* stats for num requests and creates of buffers per class
|
||||
*/
|
||||
private final AtomicLong[] requests, creates, deletes;
|
||||
|
||||
/**
|
||||
* singleton pattern.
|
||||
*/
|
||||
private static final BufferPool instance = new BufferPool();
|
||||
|
||||
/**
|
||||
* if true all allocate/free operations record the stack trace. Useful to
|
||||
* find memory leaks but slow.
|
||||
*/
|
||||
protected static boolean recordStackTraces = false;
|
||||
|
||||
/**
|
||||
* Creates a new instance of BufferPool
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private BufferPool() {
|
||||
|
||||
pools = new ConcurrentLinkedQueue[BUFF_SIZES.length];
|
||||
|
||||
creates = new AtomicLong[BUFF_SIZES.length];
|
||||
for (int i = 0; i < creates.length; i++) {
|
||||
creates[i] = new AtomicLong();
|
||||
}
|
||||
|
||||
requests = new AtomicLong[BUFF_SIZES.length + 1];
|
||||
deletes = new AtomicLong[BUFF_SIZES.length + 1];
|
||||
for (int i = 0; i < BUFF_SIZES.length + 1; i++) {
|
||||
requests[i] = new AtomicLong();
|
||||
deletes[i] = new AtomicLong();
|
||||
}
|
||||
|
||||
poolSizes = new AtomicInteger[BUFF_SIZES.length];
|
||||
for (int i = 0; i < BUFF_SIZES.length; i++) {
|
||||
pools[i] = new ConcurrentLinkedQueue<ByteBuffer>();
|
||||
poolSizes[i] = new AtomicInteger(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new buffer. The Buffer is taken from the pool or created if none is
|
||||
* available or the size exceedes the largest class.
|
||||
*
|
||||
* @param size
|
||||
* the buffer's size in bytes
|
||||
* @return a buffer of requested size
|
||||
* @throws OutOfMemoryError
|
||||
* if a buffer cannot be allocated
|
||||
*/
|
||||
public static ReusableBuffer allocate(int size) {
|
||||
ReusableBuffer tmp = instance.getNewBuffer(size);
|
||||
assert (tmp.refCount.get() == 1): "newly allocated buffer has invalid reference count: " + tmp.refCount.get();
|
||||
|
||||
if (recordStackTraces) {
|
||||
tmp.allocStack = "\n";
|
||||
for (StackTraceElement elem : new Exception().getStackTrace())
|
||||
tmp.allocStack += elem.toString() + "\n";
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer to the pool, if the buffer is reusable. Other buffers
|
||||
* are ignored.
|
||||
*
|
||||
* @param buf
|
||||
* the buffer to return
|
||||
*/
|
||||
public static void free(ReusableBuffer buf) {
|
||||
if (buf != null) {
|
||||
instance.returnBuffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer which has at least size bytes.
|
||||
*
|
||||
* @attention The returned buffer can be larger than requested!
|
||||
*/
|
||||
private ReusableBuffer getNewBuffer(int size) {
|
||||
|
||||
try {
|
||||
|
||||
// if there is a pooled buffer with sufficient capacity ...
|
||||
for (int i = 0; i < BUFF_SIZES.length; i++) {
|
||||
|
||||
if (size <= BUFF_SIZES[i]) {
|
||||
|
||||
ByteBuffer buf = pools[i].poll();
|
||||
|
||||
// if no free buffer is available in the pool ...
|
||||
if (buf == null) {
|
||||
|
||||
// ... create
|
||||
// - a direct buffer if the pool is not full yet,
|
||||
// - a non-direct buffer if the pool is full
|
||||
//
|
||||
// Thus, the first MAX_POOL_SIZES[i] buffers will be
|
||||
// pooled, whereas any additional buffers will be
|
||||
// allocated on demand and freed by the garbage
|
||||
// collector.
|
||||
|
||||
buf = creates[i].get() < MAX_POOL_SIZES[i] ? ByteBuffer.allocateDirect(BUFF_SIZES[i])
|
||||
: ByteBuffer.allocate(BUFF_SIZES[i]);
|
||||
creates[i].incrementAndGet();
|
||||
}
|
||||
|
||||
// otherwise, decrement the pool size to indicate that the
|
||||
// pooled buffer was handed out to the application
|
||||
else {
|
||||
poolSizes[i].decrementAndGet();
|
||||
}
|
||||
|
||||
requests[i].incrementAndGet();
|
||||
return new ReusableBuffer(buf, size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ... otherwise, create an unpooled buffer
|
||||
requests[BUFF_SIZES.length].incrementAndGet();
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(size);
|
||||
return new ReusableBuffer(buf, size);
|
||||
|
||||
} catch (OutOfMemoryError ex) {
|
||||
System.out.println(getStatus());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private void returnBuffer(ReusableBuffer buffer) {
|
||||
returnBuffer(buffer, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a buffer to the pool
|
||||
*/
|
||||
private void returnBuffer(ReusableBuffer buffer, boolean callFromView) {
|
||||
|
||||
if (!buffer.isReusable())
|
||||
return;
|
||||
|
||||
if (buffer.viewParent != null) {
|
||||
|
||||
// view buffer
|
||||
if (recordStackTraces) {
|
||||
|
||||
if (buffer.freeStack == null)
|
||||
buffer.freeStack = "";
|
||||
buffer.freeStack += "\n";
|
||||
|
||||
StackTraceElement[] stackTrace = new Exception().getStackTrace();
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
buffer.freeStack += stackTrace[i].toString() + "\n";
|
||||
}
|
||||
|
||||
assert (!buffer.returned) : "buffer was already released: " + buffer.freeStack;
|
||||
buffer.returned = true;
|
||||
returnBuffer(buffer.viewParent, true);
|
||||
|
||||
} else {
|
||||
|
||||
assert (!buffer.returned || callFromView) : "buffer was already released: " + buffer.freeStack;
|
||||
|
||||
if (recordStackTraces) {
|
||||
|
||||
if (buffer.freeStack == null)
|
||||
buffer.freeStack = "";
|
||||
buffer.freeStack += "\n";
|
||||
|
||||
StackTraceElement[] stackTrace = new Exception().getStackTrace();
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
buffer.freeStack += stackTrace[i].toString() + "\n";
|
||||
}
|
||||
|
||||
if (!callFromView) {
|
||||
buffer.returned = true;
|
||||
}
|
||||
|
||||
if (buffer.refCount.getAndDecrement() > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer buf = buffer.getParent();
|
||||
buf.clear();
|
||||
|
||||
// determine the pool to which the buffer is supposed to be
|
||||
// returned
|
||||
// ...
|
||||
for (int i = 0; i < BUFF_SIZES.length; i++) {
|
||||
|
||||
if (buf.capacity() == BUFF_SIZES[i]) {
|
||||
|
||||
// return direct buffers to the pool
|
||||
if (buf.isDirect()) {
|
||||
|
||||
poolSizes[i].incrementAndGet();
|
||||
pools[i].add(buf);
|
||||
|
||||
// since only direct buffers will be returned to the
|
||||
// pool, which have been counted on allocation, there is
|
||||
// no need to check the pool size here
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if the buffer is non-direct, increment the delete counter
|
||||
// and implicitly make the buffer subject to garbage
|
||||
// collection
|
||||
else {
|
||||
deletes[i].incrementAndGet();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assert (!buf.isDirect()) : "encountered direct buffer that does not fit in any of the pools (size="
|
||||
+ buf.capacity() + "): " + buffer.freeStack;
|
||||
|
||||
// if the buffer did not fit in any of the pools,
|
||||
// increment the delete counter for the unpooled buffers
|
||||
deletes[deletes.length - 1].incrementAndGet();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current pool size for a specific buffer size.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* when bufferSize is not in the pool
|
||||
*/
|
||||
public static int getPoolSize(int bufferSize) {
|
||||
for (int i = 0; i < BUFF_SIZES.length; i++) {
|
||||
if (BUFF_SIZES[i] == bufferSize) {
|
||||
return instance.poolSizes[i].get();
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Specified buffer size is not pooled. Check BufferPool configuration.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a textual representation of the pool status.
|
||||
*
|
||||
* @return a textual representation of the pool status.
|
||||
*/
|
||||
public static String getStatus() {
|
||||
|
||||
String str = "";
|
||||
for (int i = 0; i < BUFF_SIZES.length; i++) {
|
||||
str += String.format(
|
||||
"%8d: poolSize = %5d numRequests = %8d creates = %8d deletes = %8d\n",
|
||||
BUFF_SIZES[i], instance.poolSizes[i].get(), instance.requests[i].get(), instance.creates[i]
|
||||
.get(), instance.deletes[i].get());
|
||||
}
|
||||
str += String.format("unpooled (> %8d) numRequests = creates = %8d deletes = %8d",
|
||||
BUFF_SIZES[BUFF_SIZES.length - 1], instance.requests[instance.requests.length - 1].get(),
|
||||
instance.deletes[instance.deletes.length - 1].get());
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether stack traces shall be recorded when allocating and
|
||||
* freeing buffers. Since recording stack traces leads to some overhead, it
|
||||
* should only be enabled for debugging purposes.
|
||||
*
|
||||
* @param record
|
||||
*/
|
||||
public static void enableStackTraceRecording(boolean record) {
|
||||
recordStackTraces = record;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,724 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.xtreemfs.foundation.logging.Logging;
|
||||
import org.xtreemfs.foundation.logging.Logging.Category;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public final class ReusableBuffer {
|
||||
|
||||
private static final Charset ENC_UTF8 = Charset.forName("utf-8");
|
||||
|
||||
/**
|
||||
* A view buffer of parentBuffer with the requested size. For non-reusable
|
||||
* buffers this is the buffer itself
|
||||
*/
|
||||
private ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* A parent buffer which is returned to the pool
|
||||
*/
|
||||
private final ByteBuffer parentBuffer;
|
||||
|
||||
/**
|
||||
* True if the buffer can be returned to the pool
|
||||
*/
|
||||
private final boolean reusable;
|
||||
|
||||
/**
|
||||
* set to true after a buffer was returned to the pool
|
||||
*/
|
||||
protected volatile boolean returned;
|
||||
|
||||
/**
|
||||
* size (as requested), might be smaller than parentBuffer size but is
|
||||
* always equal to the (view) buffer size.
|
||||
*/
|
||||
private int size;
|
||||
|
||||
protected ReusableBuffer viewParent;
|
||||
|
||||
protected String freeStack, allocStack;
|
||||
|
||||
/**
|
||||
* reference count
|
||||
*/
|
||||
AtomicInteger refCount;
|
||||
|
||||
/**
|
||||
* Creates a new instance of ReusableBuffer. A view buffer of size is created.
|
||||
*
|
||||
* @param buffer
|
||||
* the parent buffer
|
||||
* @param size
|
||||
* the requested size
|
||||
*/
|
||||
protected ReusableBuffer(ByteBuffer buffer, int size) {
|
||||
buffer.position(0);
|
||||
buffer.limit(size);
|
||||
this.buffer = buffer.slice();
|
||||
this.parentBuffer = buffer;
|
||||
this.size = size;
|
||||
this.reusable = true;
|
||||
this.refCount = new AtomicInteger(1);
|
||||
returned = false;
|
||||
viewParent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper for a non-reusable buffer. The buffer is not used by the pool
|
||||
* when returned.
|
||||
*/
|
||||
public ReusableBuffer(ByteBuffer nonManaged) {
|
||||
this.buffer = nonManaged;
|
||||
this.size = buffer.limit();
|
||||
this.reusable = false;
|
||||
this.parentBuffer = null;
|
||||
returned = false;
|
||||
this.refCount = new AtomicInteger(1);
|
||||
viewParent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a non-reusable buffer around a byte array. Uses the
|
||||
* ByteBuffer.wrap method.
|
||||
*
|
||||
* @param data
|
||||
* the byte arry containing the data
|
||||
* @return
|
||||
*/
|
||||
public static ReusableBuffer wrap(byte[] data) {
|
||||
return new ReusableBuffer(ByteBuffer.wrap(data));
|
||||
}
|
||||
|
||||
public static ReusableBuffer wrap(byte[] data, int offset, int length) {
|
||||
assert (offset >= 0);
|
||||
assert (length >= 0);
|
||||
if (offset + length > data.length)
|
||||
throw new IllegalArgumentException("offset+length > buffer size (" + offset + "+" + length
|
||||
+ " > " + data.length);
|
||||
ByteBuffer tmp = ByteBuffer.wrap(data);
|
||||
tmp.position(offset);
|
||||
tmp.limit(offset + length);
|
||||
return new ReusableBuffer(tmp.slice());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new view buffer. This view buffer shares the same data (i.e.
|
||||
* backing byte buffer) but has independent position, limit etc.
|
||||
*/
|
||||
public ReusableBuffer createViewBuffer() {
|
||||
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
|
||||
if (this.viewParent == null) {
|
||||
|
||||
if (parentBuffer == null) {
|
||||
// wraped buffers
|
||||
ReusableBuffer view = new ReusableBuffer(this.buffer.slice());
|
||||
view.viewParent = this;
|
||||
|
||||
return view;
|
||||
|
||||
} else {
|
||||
// regular buffer
|
||||
ReusableBuffer view = new ReusableBuffer(this.parentBuffer, this.size);
|
||||
view.viewParent = this;
|
||||
this.refCount.incrementAndGet();
|
||||
|
||||
if (BufferPool.recordStackTraces) {
|
||||
view.allocStack = "\n";
|
||||
StackTraceElement[] stackTrace = new Exception().getStackTrace();
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
view.allocStack += stackTrace[i].toString() + (i < stackTrace.length - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (parentBuffer == null) {
|
||||
// wraped buffers
|
||||
ReusableBuffer view = new ReusableBuffer(this.buffer.slice());
|
||||
view.viewParent = this.viewParent;
|
||||
|
||||
return view;
|
||||
|
||||
} else {
|
||||
// regular buffer: use the parent to create a view buffer
|
||||
ReusableBuffer view = new ReusableBuffer(this.buffer, this.size);
|
||||
view.viewParent = this.viewParent;
|
||||
this.viewParent.refCount.incrementAndGet();
|
||||
|
||||
if (BufferPool.recordStackTraces) {
|
||||
view.allocStack = "\n";
|
||||
StackTraceElement[] stackTrace = new Exception().getStackTrace();
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
view.allocStack += stackTrace[i].toString() + (i < stackTrace.length - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#capacity
|
||||
*/
|
||||
public int capacity() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return this.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* May be higher than {@link #capacity()} if the parent buffer is from the {@link BufferPool} which may
|
||||
* have returned a larger buffer.
|
||||
*/
|
||||
public int capacityUnderlying() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return parentBuffer != null ? parentBuffer.capacity() : this.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#hasArray
|
||||
*/
|
||||
public boolean hasArray() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.hasArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte array of the buffer, creating a copy if the buffer is
|
||||
* not backed by an array
|
||||
*
|
||||
* @return a byte array with a copy of the data
|
||||
*/
|
||||
public byte[] array() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
byte[] array = null;
|
||||
|
||||
if (this.hasArray() && (this.viewParent == null)) {
|
||||
array = buffer.array();
|
||||
} else {
|
||||
array = new byte[this.limit()];
|
||||
final int oldPos = this.position();
|
||||
this.position(0);
|
||||
this.get(array);
|
||||
this.position(oldPos);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#flip
|
||||
*/
|
||||
public void flip() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.flip();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#compact
|
||||
*/
|
||||
public void compact() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#limit(int)
|
||||
*/
|
||||
public void limit(int l) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.limit(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#limit()
|
||||
*/
|
||||
public int limit() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.limit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#position(int)
|
||||
*/
|
||||
public void position(int p) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.position(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#position()
|
||||
*/
|
||||
public int position() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.position();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#hasRemaining
|
||||
*/
|
||||
public boolean hasRemaining() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.hasRemaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view buffer encapsulated by this ReusableBuffer.
|
||||
*
|
||||
* @return the view buffer
|
||||
*/
|
||||
public ByteBuffer getBuffer() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if this buffer is re-usable and can be returned to the
|
||||
* pool.
|
||||
*
|
||||
* @return true, if this buffer is re-usable
|
||||
*/
|
||||
public boolean isReusable() {
|
||||
// assert(!returned) :
|
||||
// "Buffer was already freed and cannot be used anymore"+this.freeStack;
|
||||
return this.reusable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent buffer.
|
||||
*
|
||||
* @return the parent buffer
|
||||
*/
|
||||
protected ByteBuffer getParent() {
|
||||
return this.parentBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#get()
|
||||
*/
|
||||
public byte get() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
public byte get(int index) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#get(byte[])
|
||||
*/
|
||||
public ReusableBuffer get(byte[] dst) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.get(dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#get(byte[], int offset, int length)
|
||||
*/
|
||||
public ReusableBuffer get(byte[] dst, int offset, int length) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.get(dst, offset, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#put(byte)
|
||||
*/
|
||||
public ReusableBuffer put(byte b) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.put(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#put(byte[])
|
||||
*/
|
||||
public ReusableBuffer put(byte[] src) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.put(src);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#put(byte[],int,int)
|
||||
*/
|
||||
public ReusableBuffer put(byte[] src, int offset, int len) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.put(src, offset, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#put(ByteBuffer)
|
||||
*/
|
||||
public ReusableBuffer put(ByteBuffer src) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.put(src);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the content of src into this buffer.
|
||||
*
|
||||
* @param src
|
||||
* the buffer to read from
|
||||
* @return this ReusableBuffer after reading
|
||||
* @see java.nio.ByteBuffer#put(ByteBuffer)
|
||||
*/
|
||||
public ReusableBuffer put(ReusableBuffer src) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.put(src.buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#getInt
|
||||
*/
|
||||
public int getInt() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#putInt(int)
|
||||
*/
|
||||
public ReusableBuffer putInt(int i) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.putInt(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getLong() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.getLong();
|
||||
}
|
||||
|
||||
public ReusableBuffer putLong(long l) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.putLong(l);
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getDouble() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.getDouble();
|
||||
}
|
||||
|
||||
public ReusableBuffer putDouble(double d) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.putDouble(d);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
int length = buffer.getInt();
|
||||
if (length > 0) {
|
||||
byte[] bytes = new byte[length];
|
||||
buffer.get(bytes);
|
||||
return new String(bytes, ENC_UTF8);
|
||||
} else if (length == 0) {
|
||||
return "";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ReusableBuffer putString(String str) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
if (str != null) {
|
||||
byte[] bytes = str.getBytes(ENC_UTF8);
|
||||
buffer.putInt(bytes.length);
|
||||
buffer.put(bytes);
|
||||
} else {
|
||||
buffer.putInt(-1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReusableBuffer putShortString(String str) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
assert (str.length() <= Short.MAX_VALUE);
|
||||
if (str != null) {
|
||||
byte[] bytes = str.getBytes(ENC_UTF8);
|
||||
buffer.putShort((short) bytes.length);
|
||||
buffer.put(bytes);
|
||||
} else {
|
||||
buffer.putInt(-1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ASCIIString getBufferBackedASCIIString() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return ASCIIString.unmarshall(this);
|
||||
}
|
||||
|
||||
public ReusableBuffer putBufferBackedASCIIString(ASCIIString str) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
if (str != null) {
|
||||
str.marshall(this);
|
||||
} else {
|
||||
buffer.putInt(-1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReusableBuffer putShort(short s) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.putShort(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public short getShort() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.getShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.ByteBuffer#isDirect
|
||||
*/
|
||||
public boolean isDirect() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.isDirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#remaining
|
||||
*/
|
||||
public int remaining() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.remaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.nio.Buffer#clear
|
||||
*/
|
||||
public void clear() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
byte[] array = new byte[this.limit()];
|
||||
this.position(0);
|
||||
this.get(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void shrink(int newSize) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
if (newSize > size) {
|
||||
throw new IllegalArgumentException("new size must not be larger than old size");
|
||||
}
|
||||
this.size = newSize;
|
||||
int oldPos = buffer.position();
|
||||
if (oldPos > newSize)
|
||||
oldPos = 0;
|
||||
|
||||
// save parent position and limit
|
||||
ByteBuffer originalBuffer;
|
||||
if (parentBuffer != null) {
|
||||
originalBuffer = parentBuffer;
|
||||
} else {
|
||||
originalBuffer = buffer;
|
||||
}
|
||||
int position = originalBuffer.position();
|
||||
int limit = originalBuffer.limit();
|
||||
|
||||
originalBuffer.position(0);
|
||||
originalBuffer.limit(newSize);
|
||||
this.buffer = originalBuffer.slice();
|
||||
buffer.position(oldPos);
|
||||
|
||||
// restore parent position and limit
|
||||
originalBuffer.position(position);
|
||||
originalBuffer.limit(limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increases the capacity of this buffer. Returns false if {@code newSize} is bigger than the capacity of
|
||||
* the underlying buffer.
|
||||
*
|
||||
* The underlying buffer can be a reusable buffer (parentBuffer != 0) or non-reusable buffer (viewParent
|
||||
* != 0).
|
||||
*/
|
||||
public boolean enlarge(int newSize) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
if (newSize == this.size) {
|
||||
return true;
|
||||
}
|
||||
if (parentBuffer == null && viewParent == null) {
|
||||
return false;
|
||||
}
|
||||
ByteBuffer underlyingBuffer = parentBuffer != null ? parentBuffer : viewParent.getBuffer();
|
||||
if (newSize > underlyingBuffer.capacity()) {
|
||||
return false;
|
||||
} else {
|
||||
this.size = newSize;
|
||||
int oldPos = buffer.position();
|
||||
if (oldPos > newSize)
|
||||
oldPos = 0;
|
||||
|
||||
// save parent position and limit
|
||||
int position = underlyingBuffer.position();
|
||||
int limit = underlyingBuffer.limit();
|
||||
|
||||
underlyingBuffer.position(0);
|
||||
underlyingBuffer.limit(newSize);
|
||||
this.buffer = underlyingBuffer.slice();
|
||||
buffer.position(oldPos);
|
||||
|
||||
// restore parent position and limit
|
||||
underlyingBuffer.position(position);
|
||||
underlyingBuffer.limit(limit);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the new range of the buffer starting from {@code offset} going for {@code length} bytes.
|
||||
*
|
||||
* The new position of the buffer will be 0 and the size/capacity will equal {@code length}.
|
||||
*/
|
||||
public void range(int offset, int length) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
|
||||
// useless call!
|
||||
if ((offset == 0) && (length == this.size))
|
||||
return;
|
||||
|
||||
if (offset >= size) {
|
||||
throw new IllegalArgumentException("offset must be < size. offset=" + offset + " size=" + size);
|
||||
}
|
||||
if (offset + length > size) {
|
||||
throw new IllegalArgumentException("offset+length must be <= size. size=" + size + " offset="
|
||||
+ offset + " length=" + length);
|
||||
}
|
||||
|
||||
this.size = length;
|
||||
|
||||
// save parent position and limit
|
||||
ByteBuffer originalBuffer;
|
||||
if (parentBuffer != null) {
|
||||
originalBuffer = parentBuffer;
|
||||
} else {
|
||||
originalBuffer = buffer;
|
||||
}
|
||||
int position = originalBuffer.position();
|
||||
int limit = originalBuffer.limit();
|
||||
|
||||
// ensure that the subsequent 'position' does not fail
|
||||
if (offset > limit)
|
||||
originalBuffer.limit(offset);
|
||||
|
||||
originalBuffer.position(offset);
|
||||
originalBuffer.limit(offset + length);
|
||||
this.buffer = originalBuffer.slice();
|
||||
assert (this.buffer.capacity() == length);
|
||||
|
||||
// restore parent position and limit
|
||||
originalBuffer.position(position);
|
||||
originalBuffer.limit(limit);
|
||||
}
|
||||
|
||||
public ReusableBuffer putBoolean(boolean bool) {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
buffer.put(bool ? (byte) 1 : (byte) 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getBoolean() {
|
||||
assert (!returned) : "Buffer was already freed and cannot be used anymore" + this.freeStack;
|
||||
return buffer.get() == 1;
|
||||
}
|
||||
|
||||
public int getRefCount() {
|
||||
if (this.viewParent == null) {
|
||||
return this.refCount.get();
|
||||
} else {
|
||||
return this.viewParent.refCount.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
|
||||
if (!returned && reusable) {
|
||||
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this,
|
||||
"buffer was finalized but not freed before! buffer = %s, refCount=%d", this.toString(), getRefCount());
|
||||
|
||||
if (allocStack != null) {
|
||||
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "stacktrace: %s", allocStack);
|
||||
if (this.viewParent != null)
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "parent stacktrace: %s",
|
||||
viewParent.allocStack);
|
||||
}
|
||||
|
||||
if (freeStack != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "freed at: %s", freeStack);
|
||||
} else if (viewParent != null && viewParent.freeStack != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "freed at: %s", viewParent.freeStack);
|
||||
}
|
||||
|
||||
if (Logging.isDebug()) {
|
||||
|
||||
byte[] data = new byte[(this.capacity() > 128) ? 128 : this.capacity()];
|
||||
this.position(0);
|
||||
this.limit(this.capacity());
|
||||
this.get(data);
|
||||
String content = new String(data);
|
||||
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "content: %s", content);
|
||||
|
||||
if (this.viewParent != null) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "view parent: %s",
|
||||
this.viewParent.toString());
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "ref count: %d",
|
||||
this.viewParent.refCount.get());
|
||||
} else {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, Category.buffer, this, "ref count: %d",
|
||||
this.refCount.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BufferPool.free(this);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReusableBuffer( capacity=" + this.capacity() + " limit=" + this.limit() + " position="
|
||||
+ this.position() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* An interface which must be implemented by checksum algorithms for XtreemFS.
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public interface ChecksumAlgorithm extends Cloneable {
|
||||
/**
|
||||
* Returns a string that identifies the algorithm, independent of
|
||||
* implementation details.
|
||||
*
|
||||
* @return name of algorithm
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Returns checksum value (as Hex-String) and resets the Algorithm.
|
||||
*
|
||||
* @return checksum
|
||||
*/
|
||||
public long getValue();
|
||||
|
||||
/**
|
||||
* Resets checksum to initial value.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void reset();
|
||||
|
||||
/**
|
||||
* Updates checksum with specified data.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void update(ByteBuffer data);
|
||||
|
||||
/**
|
||||
* returns a new instance of the checksum algorithm
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ChecksumAlgorithm clone();
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* A Factory for getting checksum algorithms from checksum provider. Implemented
|
||||
* as a Singleton.
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public class ChecksumFactory {
|
||||
/**
|
||||
* amount of cached instances/algorithm
|
||||
*/
|
||||
private static int MAX_CACHE_SIZE = 20;
|
||||
|
||||
private static ChecksumFactory self;
|
||||
|
||||
/**
|
||||
* Contains all available checksum algorithms (only one instance).
|
||||
*/
|
||||
private HashMap<String, ChecksumAlgorithm> algorithms;
|
||||
|
||||
/**
|
||||
* Contains all known checksum provider
|
||||
*/
|
||||
private HashMap<String, ChecksumProvider> knownProvider;
|
||||
|
||||
/**
|
||||
* Contains cached instances for all available checksum algorithms.
|
||||
*/
|
||||
private HashMap<String, ConcurrentLinkedQueue<ChecksumAlgorithm>> pool;
|
||||
|
||||
/**
|
||||
* creates a new ChecksumFactory
|
||||
*/
|
||||
private ChecksumFactory() {
|
||||
super();
|
||||
this.algorithms = new HashMap<String, ChecksumAlgorithm>();
|
||||
this.pool = new HashMap<String, ConcurrentLinkedQueue<ChecksumAlgorithm>>();
|
||||
this.knownProvider = new HashMap<String, ChecksumProvider>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instance of ChecksumFactory.
|
||||
*
|
||||
* @return the instance
|
||||
*/
|
||||
public static ChecksumFactory getInstance() {
|
||||
if (self == null) {
|
||||
self = new ChecksumFactory();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a specific checksum algorithm, if supported.
|
||||
*
|
||||
* @param name
|
||||
* of the algorithm
|
||||
* @return algorithm object or null, if algorithm is not supported
|
||||
*/
|
||||
public ChecksumAlgorithm getAlgorithm(String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
ConcurrentLinkedQueue<ChecksumAlgorithm> cache = pool.get(name);
|
||||
if (cache == null)
|
||||
throw new NoSuchAlgorithmException("algorithm " + name
|
||||
+ " not supported");
|
||||
|
||||
ChecksumAlgorithm algorithm = cache.poll();
|
||||
if (algorithm == null) { // cache is empty
|
||||
return algorithms.get(name).clone(); // create new instance
|
||||
} else {
|
||||
return algorithm; // return caches instance
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a specific checksum algorithm for caching.
|
||||
*
|
||||
* @param instance
|
||||
* of the algorithm
|
||||
*/
|
||||
public void returnAlgorithm(ChecksumAlgorithm algorithm) {
|
||||
ConcurrentLinkedQueue<ChecksumAlgorithm> cache = pool.get(algorithm
|
||||
.getName());
|
||||
if (cache.size() < MAX_CACHE_SIZE) {
|
||||
algorithm.reset();
|
||||
cache.add(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new provider to factory and adds all supported algorithms from the
|
||||
* provider to the algorithms-list. NOTE: Existing algorithms will be
|
||||
* overridden when the new provider contains the same algorithm (maybe
|
||||
* another implementation).
|
||||
*
|
||||
* @param provider
|
||||
*/
|
||||
public void addProvider(ChecksumProvider provider) {
|
||||
knownProvider.put(provider.getName(), provider);
|
||||
for (ChecksumAlgorithm algorithm : provider.getSupportedAlgorithms()) {
|
||||
addAlgorithm(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new Algorithm to factory. NOTE: The same existing algorithm will
|
||||
* be overridden.
|
||||
*
|
||||
* @param algorithm
|
||||
*/
|
||||
public void addAlgorithm(ChecksumAlgorithm algorithm) {
|
||||
algorithms.put(algorithm.getName(), algorithm);
|
||||
pool.put(algorithm.getName(),
|
||||
new ConcurrentLinkedQueue<ChecksumAlgorithm>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a provider, but not the added algorithms.
|
||||
*
|
||||
* @param provider
|
||||
*/
|
||||
public void removeProvider(ChecksumProvider provider) {
|
||||
knownProvider.remove(provider.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an algorithm.
|
||||
*
|
||||
* @param algorithm
|
||||
*/
|
||||
public void removeAlgorithm(String algorithm) {
|
||||
algorithms.remove(algorithm);
|
||||
pool.remove(algorithm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* An abstract class which must be implemented by a checksum provider for
|
||||
* XtreemFS.
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public abstract class ChecksumProvider {
|
||||
/**
|
||||
* contains the supported algorithms
|
||||
*/
|
||||
protected HashMap<String, ChecksumAlgorithm> algorithms;
|
||||
|
||||
protected ChecksumProvider() {
|
||||
super();
|
||||
this.algorithms = new HashMap<String, ChecksumAlgorithm>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the provider.
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/**
|
||||
* Returns all from this provider supported checksum algorithms.
|
||||
*
|
||||
* @return a collection with ChecksumAlgorithms
|
||||
*/
|
||||
public Collection<ChecksumAlgorithm> getSupportedAlgorithms() {
|
||||
return algorithms.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* adds an algorithm to the map
|
||||
*
|
||||
* @param newAlgorithm
|
||||
*/
|
||||
protected void addAlgorithm(ChecksumAlgorithm newAlgorithm) {
|
||||
this.algorithms.put(newAlgorithm.getName(), newAlgorithm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums;
|
||||
|
||||
/**
|
||||
* An interface for checksum algorithms, which are based on computations on
|
||||
* strings.
|
||||
*
|
||||
* 02.09.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public interface StringChecksumAlgorithm extends ChecksumAlgorithm {
|
||||
/**
|
||||
* Updates checksum with specified data.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void digest(String data);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums.algorithms;
|
||||
|
||||
/**
|
||||
* The Adler32 algorithm. It uses the Java internal implementation.
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Adler32 extends JavaChecksumAlgorithm {
|
||||
|
||||
public Adler32() {
|
||||
super(new java.util.zip.Adler32(), "Adler32");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#clone()
|
||||
*/
|
||||
@Override
|
||||
public Adler32 clone() {
|
||||
return new Adler32();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums.algorithms;
|
||||
|
||||
/**
|
||||
* The CRC32 algorithm. It uses the Java internal implementation.
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CRC32 extends JavaChecksumAlgorithm {
|
||||
|
||||
public CRC32() {
|
||||
super(new java.util.zip.CRC32(), "CRC32");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#clone()
|
||||
*/
|
||||
@Override
|
||||
public CRC32 clone() {
|
||||
return new CRC32();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums.algorithms;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.zip.Checksum;
|
||||
|
||||
import org.xtreemfs.foundation.checksums.ChecksumAlgorithm;
|
||||
|
||||
/**
|
||||
* An abstract wrapper for Java internal checksums.
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
abstract public class JavaChecksumAlgorithm<RealJavaAlgorithm extends Checksum>
|
||||
implements ChecksumAlgorithm {
|
||||
/**
|
||||
* the class, which really implements the selected algorithm
|
||||
*/
|
||||
protected RealJavaAlgorithm realAlgorithm;
|
||||
|
||||
protected String name;
|
||||
|
||||
public JavaChecksumAlgorithm(RealJavaAlgorithm realAlgorithm, String name) {
|
||||
super();
|
||||
this.realAlgorithm = realAlgorithm;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#digest(java.nio.ByteBuffer)
|
||||
*/
|
||||
@Override
|
||||
public void update(ByteBuffer data) {
|
||||
byte[] array;
|
||||
|
||||
if (data.hasArray()) {
|
||||
array = data.array();
|
||||
} else {
|
||||
array = new byte[data.capacity()];
|
||||
final int oldPos = data.position();
|
||||
data.position(0);
|
||||
data.get(array);
|
||||
data.position(oldPos);
|
||||
}
|
||||
|
||||
realAlgorithm.update(array, 0, array.length);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#getValue()
|
||||
*/
|
||||
@Override
|
||||
public long getValue() {
|
||||
final long tmp = realAlgorithm.getValue();
|
||||
realAlgorithm.reset();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
realAlgorithm.reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#clone()
|
||||
*/
|
||||
@Override
|
||||
public abstract JavaChecksumAlgorithm<?> clone();
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums.algorithms;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.xtreemfs.foundation.checksums.StringChecksumAlgorithm;
|
||||
|
||||
/**
|
||||
* The Java algorithm, which is used for string.hashCode(). It uses the Java
|
||||
* internal implementation.
|
||||
*
|
||||
* 02.09.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public class JavaHash implements StringChecksumAlgorithm {
|
||||
private Long hash = null;
|
||||
|
||||
private String name = "Java-Hash";
|
||||
|
||||
/**
|
||||
* Updates checksum with specified data.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void digest(String data) {
|
||||
this.hash = Long.valueOf(data.hashCode());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#digest(java.nio.ByteBuffer)
|
||||
*/
|
||||
@Override
|
||||
public void update(ByteBuffer data) {
|
||||
byte[] array;
|
||||
|
||||
if (data.hasArray()) {
|
||||
array = data.array();
|
||||
} else {
|
||||
array = new byte[data.capacity()];
|
||||
final int oldPos = data.position();
|
||||
data.position(0);
|
||||
data.get(array);
|
||||
data.position(oldPos);
|
||||
}
|
||||
|
||||
this.hash = (long)new String(array).hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#getValue()
|
||||
*/
|
||||
@Override
|
||||
public long getValue() {
|
||||
long value;
|
||||
if (this.hash != null)
|
||||
value = this.hash;
|
||||
else
|
||||
value = 0;
|
||||
reset();
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
hash = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#clone()
|
||||
*/
|
||||
@Override
|
||||
public JavaHash clone() {
|
||||
return new JavaHash();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums.algorithms;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.xtreemfs.foundation.checksums.StringChecksumAlgorithm;
|
||||
|
||||
/**
|
||||
* The SDBM algorithm.
|
||||
*
|
||||
* 02.09.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public class SDBM implements StringChecksumAlgorithm {
|
||||
private Long hash = null;
|
||||
|
||||
private String name = "SDBM";
|
||||
|
||||
/**
|
||||
* Updates checksum with specified data.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void digest(String data) {
|
||||
this.hash = sdbmHash(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#digest(java.nio.ByteBuffer)
|
||||
*/
|
||||
@Override
|
||||
public void update(ByteBuffer data) {
|
||||
byte[] array;
|
||||
|
||||
if (data.hasArray()) {
|
||||
array = data.array();
|
||||
} else {
|
||||
array = new byte[data.capacity()];
|
||||
final int oldPos = data.position();
|
||||
data.position(0);
|
||||
data.get(array);
|
||||
data.position(oldPos);
|
||||
}
|
||||
|
||||
this.hash = sdbmHash(new String(array));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#getValue()
|
||||
*/
|
||||
@Override
|
||||
public long getValue() {
|
||||
long value;
|
||||
if (this.hash != null)
|
||||
value = this.hash;
|
||||
else
|
||||
value = 0;
|
||||
reset();
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumAlgorithm#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
hash = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.common.checksum.ChecksumAlgorithm#clone()
|
||||
*/
|
||||
@Override
|
||||
public SDBM clone() {
|
||||
return new SDBM();
|
||||
}
|
||||
|
||||
/**
|
||||
* SDBM algorithm
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
protected static long sdbmHash(String str) {
|
||||
long hash = 0;
|
||||
for (int c : str.toCharArray()) {
|
||||
hash = c + (hash << 6) + (hash << 16) - hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.checksums.provider;
|
||||
|
||||
import org.xtreemfs.foundation.checksums.ChecksumProvider;
|
||||
|
||||
/**
|
||||
* A provider for Java internal checksums. offers the following algorithms:
|
||||
* Adler32, CRC32, MD5, Java-Hash
|
||||
*
|
||||
* 19.08.2008
|
||||
*
|
||||
* @author clorenz
|
||||
*/
|
||||
public class JavaChecksumProvider extends ChecksumProvider {
|
||||
private static String NAME = "Java Checksum Provider";
|
||||
|
||||
/**
|
||||
* creates a new JavaChecksumProvider
|
||||
*/
|
||||
public JavaChecksumProvider() {
|
||||
super();
|
||||
|
||||
addAlgorithm(new org.xtreemfs.foundation.checksums.algorithms.Adler32());
|
||||
addAlgorithm(new org.xtreemfs.foundation.checksums.algorithms.CRC32());
|
||||
/*try {
|
||||
addAlgorithm(new org.xtreemfs.foundation.checksums.algorithms.JavaMessageDigestAlgorithm(
|
||||
"MD5", "MD5"));
|
||||
addAlgorithm(new org.xtreemfs.foundation.checksums.algorithms.JavaMessageDigestAlgorithm(
|
||||
"SHA1", "SHA-1"));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Logging.logMessage(Logging.LEVEL_WARN, this, e.getMessage()
|
||||
+ " in your java-installation");
|
||||
}*/
|
||||
addAlgorithm(new org.xtreemfs.foundation.checksums.algorithms.JavaHash());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xtreemfs.foundation.checksums.ChecksumProvider#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.json;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class JSONCharBufferString implements JSONInput {
|
||||
|
||||
CharBuffer cb;
|
||||
|
||||
/** Creates a new instance of JSONCharBufferString */
|
||||
public JSONCharBufferString(CharBuffer cb) {
|
||||
assert (cb != null);
|
||||
|
||||
this.cb = cb;
|
||||
this.cb.position(0);
|
||||
}
|
||||
|
||||
public char read() throws JSONException {
|
||||
try {
|
||||
return cb.get();
|
||||
} catch(BufferUnderflowException ex) {
|
||||
throw new JSONException("Reached end of buffer");
|
||||
}
|
||||
}
|
||||
|
||||
public int skip(int skip) {
|
||||
try {
|
||||
|
||||
cb.position(cb.position()+skip);
|
||||
|
||||
return skip;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "JSONCharBufferString backed by "+cb.toString();
|
||||
}
|
||||
|
||||
public boolean hasMore() {
|
||||
return cb.hasRemaining();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.json;
|
||||
|
||||
/**
|
||||
* Thrown by the JSON parser and writer.
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class JSONException extends java.lang.Exception {
|
||||
|
||||
/***/
|
||||
private static final long serialVersionUID = 2422241603599209392L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>JSONException</code> without detail
|
||||
* message.
|
||||
*/
|
||||
public JSONException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>JSONException</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg
|
||||
* the detail message.
|
||||
*/
|
||||
public JSONException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.json;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public interface JSONInput {
|
||||
|
||||
|
||||
/**
|
||||
* reads a single char
|
||||
*
|
||||
* @return the character at the current position is returned
|
||||
*/
|
||||
public char read() throws JSONException;
|
||||
|
||||
/**
|
||||
* It checks if there are more characters
|
||||
*/
|
||||
public boolean hasMore();
|
||||
|
||||
/**
|
||||
* Skips skip characters
|
||||
*
|
||||
* @param skip
|
||||
* num characters to skip
|
||||
* @return the number of characters skipped
|
||||
*/
|
||||
public int skip(int skip);
|
||||
|
||||
/**
|
||||
* Get a string representation.
|
||||
*
|
||||
* @return A string representation of the this JSONString.
|
||||
*/
|
||||
public String toString();
|
||||
|
||||
}
|
||||
329
java/foundation/src/org/xtreemfs/foundation/json/JSONParser.java
Normal file
329
java/foundation/src/org/xtreemfs/foundation/json/JSONParser.java
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.json;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JSON Parser routines. This parser accepts any value as top level element, not
|
||||
* just an object or array.
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class JSONParser {
|
||||
|
||||
/**
|
||||
* Creates a new instance of JSONParser
|
||||
*/
|
||||
public JSONParser() {
|
||||
}
|
||||
|
||||
private static String parseString(JSONInput input) throws JSONException {
|
||||
|
||||
boolean nonEscaped = true;
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
while (input.hasMore()) {
|
||||
char ch = input.read();
|
||||
|
||||
if (nonEscaped) {
|
||||
if (ch == '\\') {
|
||||
nonEscaped = false;
|
||||
continue;
|
||||
}
|
||||
else if (ch == '"') {
|
||||
return str.toString();
|
||||
}
|
||||
else {
|
||||
str.append(ch);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ch == 'n') {
|
||||
str.append('\n');
|
||||
} else if (ch == 'r') {
|
||||
str.append('\r');
|
||||
} else if (ch == 't') {
|
||||
str.append('\t');
|
||||
} else {
|
||||
str.append(ch);
|
||||
}
|
||||
}
|
||||
|
||||
nonEscaped = true;
|
||||
}
|
||||
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected end while parsing string");
|
||||
|
||||
}
|
||||
|
||||
private static Object parseNumber(JSONInput input) throws JSONException {
|
||||
|
||||
StringBuilder str = new StringBuilder();
|
||||
input.skip(-1);
|
||||
|
||||
boolean isFP = false;
|
||||
|
||||
while (input.hasMore()) {
|
||||
char ch = input.read();
|
||||
|
||||
if ((ch == '-') || (ch >= '0') && (ch <= '9')) {
|
||||
str.append(ch);
|
||||
} else if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
|
||||
str.append(ch);
|
||||
isFP = true;
|
||||
} else {
|
||||
input.skip(-1);
|
||||
if (isFP)
|
||||
return new BigDecimal(str.toString());
|
||||
else
|
||||
return Long.valueOf(str.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (isFP)
|
||||
return new BigDecimal(str.toString());
|
||||
else
|
||||
return Long.valueOf(str.toString());
|
||||
}
|
||||
|
||||
private static Object parseArray(JSONInput input) throws JSONException {
|
||||
LinkedList<Object> arr = new LinkedList<Object>();
|
||||
|
||||
while (input.hasMore()) {
|
||||
char ch = input.read();
|
||||
|
||||
if (ch == ']') {
|
||||
return arr;
|
||||
} else if (ch == ',') {
|
||||
arr.add(parseJSON(input));
|
||||
} else if ((ch == ' ') || (ch == '\t')) {
|
||||
continue;
|
||||
} else {
|
||||
input.skip(-1);
|
||||
arr.add(parseJSON(input));
|
||||
}
|
||||
}
|
||||
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected end while parsing array");
|
||||
}
|
||||
|
||||
private static Object parseObject(JSONInput input) throws JSONException {
|
||||
|
||||
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
while (input.hasMore()) {
|
||||
char ch = input.read();
|
||||
|
||||
if (ch == '}') {
|
||||
return map;
|
||||
}
|
||||
// skip all ws
|
||||
if ((ch == ' ') || (ch == '\t')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = parseString(input);
|
||||
ch = input.read();
|
||||
|
||||
while ((ch == ' ') || (ch == '\t')) {
|
||||
ch = input.read();
|
||||
}
|
||||
|
||||
if (ch != ':') {
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected token '"
|
||||
+ ((char) ch) + "' or EOF. Expected : in Object.");
|
||||
}
|
||||
|
||||
while ((ch == ' ') || (ch == '\t')) {
|
||||
ch = input.read();
|
||||
}
|
||||
|
||||
Object value = parseJSON(input);
|
||||
map.put(name, value);
|
||||
ch = input.read();
|
||||
|
||||
while ((ch == ' ') || (ch == '\t')) {
|
||||
ch = input.read();
|
||||
}
|
||||
|
||||
if (ch == '}') {
|
||||
return map;
|
||||
}
|
||||
if (ch != ',') {
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected token '"
|
||||
+ ((char) ch) + "' or EOF. Expected , or } in Object.");
|
||||
}
|
||||
}
|
||||
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected end while parsing object");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON message.
|
||||
*
|
||||
* @return the objects encoded in input.
|
||||
* @attention This routine may cause a StackOverflow exception when parsing
|
||||
* incorrect, very deep or maliciously malformed JSON messages.
|
||||
* @param input
|
||||
* the JSON string
|
||||
* @throws org.xtreemos.wp34.mrc.utils.JSONException
|
||||
* if input is not valid JSON
|
||||
*/
|
||||
public static Object parseJSON(JSONInput input) throws JSONException {
|
||||
|
||||
while (input.hasMore()) {
|
||||
char ch = input.read();
|
||||
|
||||
if (ch == '[') {
|
||||
return parseArray(input);
|
||||
} else if (ch == '{') {
|
||||
return parseObject(input);
|
||||
} else if (ch == '"') {
|
||||
return parseString(input);
|
||||
} else if ((ch == '-') || ((ch >= '0') && (ch <= '9'))) {
|
||||
return parseNumber(input);
|
||||
} else if (ch == 't') {
|
||||
input.skip(3);
|
||||
return Boolean.valueOf(true);
|
||||
} else if (ch == 'f') {
|
||||
input.skip(4);
|
||||
return Boolean.valueOf(false);
|
||||
} else if (ch == 'n') {
|
||||
input.skip(3);
|
||||
return null;
|
||||
} else if ((ch == ' ') || (ch == '\t')) {
|
||||
continue;
|
||||
} else {
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected token '"
|
||||
+ ((char) ch) + "' expected Object, Array or Value.");
|
||||
}
|
||||
}
|
||||
|
||||
throw new JSONException("[ E | JSONParser ] Unexpected end while parsing root element");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded message from an object. Can handle Boolean,
|
||||
* Integer, Long, BigDecimal, List and Map.
|
||||
*
|
||||
* @param input
|
||||
* object to encode, objects can be nested.
|
||||
* @return a JSON encoded message
|
||||
* @throws org.xtreemos.wp34.mrc.utils.JSONException
|
||||
* if there are one or more objects it cannot encode
|
||||
*/
|
||||
public static String writeJSON(Object input) throws JSONException {
|
||||
return writeJSON(input,new StringBuilder()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded message from an object. Can handle Boolean,
|
||||
* Integer, Long, BigDecimal, List and Map.
|
||||
*
|
||||
* @param input
|
||||
* object to encode, objects can be nested.
|
||||
* @return a JSON encoded message
|
||||
* @throws org.xtreemos.wp34.mrc.utils.JSONException
|
||||
* if there are one or more objects it cannot encode
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static StringBuilder writeJSON(Object input, StringBuilder result) throws JSONException {
|
||||
|
||||
if (input == null) {
|
||||
return result.append("null");
|
||||
} else if (input instanceof Boolean) {
|
||||
return result.append(((Boolean) input).booleanValue() ? "true" : "false");
|
||||
} else if (input instanceof BigDecimal) {
|
||||
return result.append(((BigDecimal) input).toString());
|
||||
} else if (input instanceof Integer) {
|
||||
return result.append((Integer) input);
|
||||
} else if (input instanceof Long) {
|
||||
return result.append((Long) input);
|
||||
} else if (input instanceof String) {
|
||||
return writeJSONString(input,result);
|
||||
} else if (input instanceof Map) {
|
||||
return writeJSONObject(input,result);
|
||||
} else if (input instanceof Collection) {
|
||||
return writeJSONArray(input,result);
|
||||
} else {
|
||||
throw new JSONException(
|
||||
"[ E | JSONParser ] Unexpected Object type: "
|
||||
+ input.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static StringBuilder writeJSONObject(Object input, StringBuilder result) throws JSONException {
|
||||
Map<Object, Object> map = (Map) input;
|
||||
result.append("{");
|
||||
int i = 1;
|
||||
for (Object key : map.keySet()) {
|
||||
writeJSONString(key.toString(),result);
|
||||
result.append(":");
|
||||
writeJSON(map.get(key),result);
|
||||
if (i < map.size())
|
||||
result.append(",");
|
||||
i++;
|
||||
}
|
||||
return result.append("}");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static StringBuilder writeJSONArray(Object input, StringBuilder result) throws JSONException {
|
||||
Collection<Object> arr = (Collection<Object>) input;
|
||||
result.append("[");
|
||||
int i = 1;
|
||||
for (Object obj : arr) {
|
||||
writeJSON(obj,result);
|
||||
if (i < arr.size())
|
||||
result.append(",");
|
||||
i++;
|
||||
}
|
||||
return result.append("]");
|
||||
}
|
||||
|
||||
private static StringBuilder writeJSONString(Object input, StringBuilder result) {
|
||||
/*
|
||||
* This is 10 times faster than using str.replace
|
||||
*/
|
||||
final String str = input.toString();
|
||||
result.append("\"");
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char ch = str.charAt(i);
|
||||
|
||||
switch (ch) {
|
||||
case '\n' : result.append("\\n"); break;
|
||||
case '\r' : result.append("\\r"); break;
|
||||
case '\t' : result.append("\\t"); break;
|
||||
case '"' : result.append("\\\""); break;
|
||||
case '\\' : result.append("\\\\"); break;
|
||||
case '/' : result.append("\\/"); break;
|
||||
default: result.append(ch);
|
||||
}
|
||||
}
|
||||
result.append("\"");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static String toJSON(Object... args) throws JSONException {
|
||||
List<Object> argList = new ArrayList<Object>(args.length);
|
||||
for (Object arg : args)
|
||||
argList.add(arg);
|
||||
|
||||
return writeJSON(argList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck, Jan Stender,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.json;
|
||||
|
||||
|
||||
/**
|
||||
* This class is necessary because the StringReader cannot skip back once the
|
||||
* end is reached.
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class JSONString implements JSONInput {
|
||||
|
||||
String str;
|
||||
|
||||
int position;
|
||||
|
||||
/**
|
||||
* Creates a new instance of JSONString
|
||||
*
|
||||
* @param str
|
||||
* the JSON message
|
||||
*/
|
||||
public JSONString(String str) {
|
||||
this.str = str;
|
||||
position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* reads a single char
|
||||
*
|
||||
* @return the character at the current position is returned
|
||||
*/
|
||||
public char read() throws JSONException {
|
||||
try {
|
||||
return str.charAt(position++);
|
||||
}
|
||||
catch (StringIndexOutOfBoundsException ex) {
|
||||
throw new JSONException("Reach the end of the string");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public boolean hasMore() {
|
||||
return position < str.length();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skips skip characters
|
||||
*
|
||||
* @param skip
|
||||
* num characters to skip
|
||||
* @return the number of characters skipped
|
||||
*/
|
||||
public int skip(int skip) {
|
||||
if (((position + skip) < 0) || ((position + skip) >= str.length())) {
|
||||
return 0;
|
||||
} else {
|
||||
position = position + skip;
|
||||
return skip;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string representation.
|
||||
*
|
||||
* @return A string representation of the this JSONString.
|
||||
*/
|
||||
public String toString() {
|
||||
return "JSONString pos=" + position + " str=" + str;
|
||||
}
|
||||
|
||||
}
|
||||
274
java/foundation/src/org/xtreemfs/foundation/logging/Logging.java
Normal file
274
java/foundation/src/org/xtreemfs/foundation/logging/Logging.java
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.logging;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class Logging {
|
||||
|
||||
public enum Category {
|
||||
/**
|
||||
* enable logging for all categories (no real category)
|
||||
*/
|
||||
all,
|
||||
/**
|
||||
* logs messages pertaining to buffers
|
||||
*/
|
||||
buffer,
|
||||
/**
|
||||
* log messaages pertaining to service lifecycles (threads)
|
||||
*/
|
||||
lifecycle,
|
||||
/**
|
||||
* network-related log messages
|
||||
*/
|
||||
net,
|
||||
/**
|
||||
* authorization-related log messages
|
||||
*/
|
||||
auth,
|
||||
/**
|
||||
* log messages pertaining to the request flow through the stages
|
||||
*/
|
||||
stage,
|
||||
/**
|
||||
* log messages pertaining to any kind of request processing
|
||||
*/
|
||||
proc,
|
||||
/**
|
||||
*
|
||||
*/
|
||||
misc,
|
||||
/**
|
||||
* log messages pertaining storage on OSD or database access on MRC/DIR
|
||||
*/
|
||||
storage,
|
||||
/**
|
||||
* logs messages pertaining to replication
|
||||
*/
|
||||
replication,
|
||||
/**
|
||||
* logs messages from additional tools
|
||||
*/
|
||||
tool,
|
||||
/**
|
||||
* logs messages from tests
|
||||
*/
|
||||
test
|
||||
}
|
||||
|
||||
protected static final char ABBREV_LEVEL_INFO = 'I';
|
||||
|
||||
protected static final char ABBREV_LEVEL_DEBUG = 'D';
|
||||
|
||||
protected static final char ABBREV_LEVEL_WARN = 'W';
|
||||
|
||||
protected static final char ABBREV_LEVEL_ERROR = 'E';
|
||||
|
||||
protected static final char ABBREV_LEVEL_TRACE = 'T';
|
||||
|
||||
public static final int LEVEL_EMERG = 0;
|
||||
|
||||
public static final int LEVEL_ALERT = 1;
|
||||
|
||||
public static final int LEVEL_CRIT = 2;
|
||||
|
||||
public static final int LEVEL_ERROR = 3;
|
||||
|
||||
public static final int LEVEL_WARN = 4;
|
||||
|
||||
public static final int LEVEL_NOTICE = 5;
|
||||
|
||||
public static final int LEVEL_INFO = 6;
|
||||
|
||||
public static final int LEVEL_DEBUG = 7;
|
||||
|
||||
public static final String FORMAT_PATTERN = "[ %c | %-20s | %-15s | %3d | %15s ] %s";
|
||||
|
||||
private static PrintStream out = System.out;
|
||||
|
||||
protected static Logging instance;
|
||||
|
||||
protected static boolean tracingEnabled = false;
|
||||
|
||||
private final int level;
|
||||
|
||||
private final int catMask;
|
||||
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd HH:mm:ss");
|
||||
|
||||
/**
|
||||
* Creates a new instance of Logging
|
||||
*/
|
||||
private Logging(int level, int catMask) {
|
||||
|
||||
if (level < 0)
|
||||
this.level = 0;
|
||||
else
|
||||
this.level = level;
|
||||
|
||||
this.catMask = catMask;
|
||||
|
||||
instance = this;
|
||||
|
||||
System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public static void redirect(PrintStream out) {
|
||||
Logging.out = out;
|
||||
}
|
||||
|
||||
public static String truncateString(String string, int maxLength) {
|
||||
return (string.length() > maxLength) ?
|
||||
(string.substring(0, maxLength - 3) + "...") : string;
|
||||
}
|
||||
|
||||
public static void logMessage(int level, Category cat, Object me, String formatPattern, Object... args) {
|
||||
checkIfInitializedOrThrow();
|
||||
|
||||
// if the level is appropriate as well as the category, or the category
|
||||
// is 'all', log the message
|
||||
if (level <= instance.level && (cat == Category.all || (2 << cat.ordinal() & instance.catMask) > 0)) {
|
||||
|
||||
char levelName = getLevelName(level);
|
||||
|
||||
out.println(String.format(FORMAT_PATTERN, levelName,
|
||||
me == null ? "-" : truncateString(me instanceof Class ? ((Class) me).getSimpleName(): me.getClass().getSimpleName(), 20),
|
||||
truncateString(Thread.currentThread().getName(), 15),
|
||||
Thread.currentThread().getId(),
|
||||
getTimeStamp(),
|
||||
String.format(formatPattern, args)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkIfInitializedOrThrow() {
|
||||
if (instance == null) {
|
||||
throw new RuntimeException(
|
||||
"Cannot log message because the logging is not initialized yet. Did you forget to call Logging.start(...) in your code?");
|
||||
}
|
||||
}
|
||||
|
||||
public static void logMessage(int level, Object me, String formatPattern, Object... args) {
|
||||
logMessage(level, Category.all, me, formatPattern, args);
|
||||
}
|
||||
|
||||
public static void logError(int level, Object me, Throwable msg) {
|
||||
checkIfInitializedOrThrow();
|
||||
|
||||
// if the level is appropriate, log the message
|
||||
if (level <= instance.level) {
|
||||
|
||||
char levelName = getLevelName(level);
|
||||
|
||||
out.println(String.format(FORMAT_PATTERN, levelName,
|
||||
me == null ? "-" : (me instanceof Class ? ((Class) me).getSimpleName(): me.getClass().getSimpleName()),
|
||||
Thread.currentThread().getName(), Thread.currentThread().getId(),
|
||||
getTimeStamp(), msg.toString()));
|
||||
for (StackTraceElement elem : msg.getStackTrace()) {
|
||||
out.println(" ... " + elem.toString());
|
||||
}
|
||||
if (msg.getCause() != null) {
|
||||
out.println(String.format(FORMAT_PATTERN, levelName, me == null ? "-" : me.getClass()
|
||||
.getSimpleName(), Thread.currentThread().getName(), Thread.currentThread().getId(),
|
||||
getTimeStamp(), "root cause: " + msg.getCause()));
|
||||
for (StackTraceElement elem : msg.getCause().getStackTrace()) {
|
||||
out.println(" ... " + elem.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void logUserError(int level, Category cat, Object me, Throwable msg) {
|
||||
checkIfInitializedOrThrow();
|
||||
|
||||
// if the level is appropriate as well as the category, or the category
|
||||
// is 'all', log the message
|
||||
if (level <= instance.level && (cat == Category.all || (2 << cat.ordinal() & instance.catMask) > 0)) {
|
||||
|
||||
char levelName = getLevelName(level);
|
||||
|
||||
out.println(String.format(FORMAT_PATTERN, levelName, me == null ? "-" : me.getClass()
|
||||
.getSimpleName(), Thread.currentThread().getName(), Thread.currentThread().getId(),
|
||||
getTimeStamp(), msg.toString()));
|
||||
for (StackTraceElement elem : msg.getStackTrace()) {
|
||||
out.println(" ... " + elem.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static char getLevelName(int level) {
|
||||
switch (level) {
|
||||
case LEVEL_EMERG:
|
||||
case LEVEL_ALERT:
|
||||
case LEVEL_CRIT:
|
||||
case LEVEL_ERROR:
|
||||
return ABBREV_LEVEL_ERROR;
|
||||
case LEVEL_WARN:
|
||||
return ABBREV_LEVEL_WARN;
|
||||
case LEVEL_NOTICE:
|
||||
case LEVEL_INFO:
|
||||
return ABBREV_LEVEL_INFO;
|
||||
case LEVEL_DEBUG:
|
||||
return ABBREV_LEVEL_DEBUG;
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static void start(int level, Category... categories) {
|
||||
if (instance == null) {
|
||||
|
||||
int catMask = 0;
|
||||
for (Category cat : categories) {
|
||||
|
||||
if (cat == Category.all)
|
||||
catMask = -1;
|
||||
|
||||
catMask |= 2 << cat.ordinal();
|
||||
}
|
||||
|
||||
if(categories.length == 0)
|
||||
catMask = -1;
|
||||
|
||||
instance = new Logging(level, catMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDebug() {
|
||||
if (instance == null)
|
||||
return false;
|
||||
else
|
||||
return instance.level >= LEVEL_DEBUG;
|
||||
}
|
||||
|
||||
public static boolean isInfo() {
|
||||
if (instance == null)
|
||||
return false;
|
||||
else
|
||||
return instance.level >= LEVEL_INFO;
|
||||
}
|
||||
|
||||
public static boolean isNotice() {
|
||||
if (instance == null)
|
||||
return false;
|
||||
else
|
||||
return instance.level >= LEVEL_NOTICE;
|
||||
}
|
||||
|
||||
private static String getTimeStamp() {
|
||||
return dateFormat.format(new Date());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 by Bjoern Kolbeck,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.logging;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bjko
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static final char LEVEL_INFO = 'I';
|
||||
public static final char LEVEL_DEBUG = 'D';
|
||||
public static final char LEVEL_WARN = 'W';
|
||||
public static final char LEVEL_ERROR = 'E';
|
||||
|
||||
|
||||
public static void logMessage(char level, Object me, String msg) {
|
||||
if (me == null) {
|
||||
System.out.println(String.format("[ %c | %-20s | %3d ] %s",
|
||||
level,"?",Thread.currentThread().getId(),
|
||||
msg));
|
||||
} else {
|
||||
System.out.println(String.format("[ %c | %-20s | %3d ] %s",
|
||||
level,me.getClass().getSimpleName(),Thread.currentThread().getId(),
|
||||
msg));
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a new instance of Utils */
|
||||
public Utils() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.monitoring;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* The class provides the ability to monitor data. It could monitor multiple data for each key.<br>
|
||||
* NOTE: This class is thread-safe. <br>
|
||||
* 22.07.2009
|
||||
*/
|
||||
public class ListMonitoring<V> extends Monitoring<List<V>> {
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 by Christian Lorenz,
|
||||
* Zuse Institute Berlin
|
||||
*
|
||||
* Licensed under the BSD License, see LICENSE file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.xtreemfs.foundation.monitoring;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* The class provides the ability to monitor data. The data must be added via push (put-method). For getting the
|
||||
* contained data poll (get-method) and push (via listeners) is supported.<br>
|
||||
* NOTE: This class is thread-safe. <br>
|
||||
* 22.07.2009
|
||||
*/
|
||||
public class Monitoring<V> {
|
||||
/**
|
||||
* contains the monitored data
|
||||
*/
|
||||
protected ConcurrentHashMap<String, V> datasets;
|
||||
|
||||
/**
|
||||
* contains the registered listeners
|
||||
*/
|
||||
protected ConcurrentHashMap<String, List<MonitoringListener<V>>> listeners;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Monitoring() {
|
||||
datasets = new ConcurrentHashMap<String, V>();
|
||||
listeners = new ConcurrentHashMap<String, List<MonitoringListener<V>>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the value to the given key and overwrites the old value. Notifies all associated listeners.
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public V put(String key, V value) {
|
||||
assert (key != null && value != null);
|
||||
|
||||
V oldValue = datasets.put(key, value);
|
||||
|
||||
// check if listeners are registered
|
||||
if (listeners.containsKey(key)) {
|
||||
MonitoringEvent<V> event = new MonitoringEvent<V>(this, key, value);
|
||||
for (MonitoringListener<V> listener : listeners.get(key))
|
||||
listener.valueAddedOrChanged(event);
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @return
|
||||
* @see java.util.HashMap#get(java.lang.Object)
|
||||
*/
|
||||
public V get(String key) {
|
||||
return datasets.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @return
|
||||
* @see java.util.HashMap#containsKey(java.lang.Object)
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
return datasets.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.util.HashMap#entrySet()
|
||||
*/
|
||||
public Set<Entry<String, V>> entrySet() {
|
||||
return datasets.entrySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @return
|
||||
* @see java.util.HashMap#remove(java.lang.Object)
|
||||
*/
|
||||
public V remove(String key) {
|
||||
return datasets.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.util.HashMap#size()
|
||||
*/
|
||||
public int size() {
|
||||
return datasets.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.util.AbstractMap#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return datasets.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener for the specified key. If the value of the key changes, the associated listeners
|
||||
* will be notified.
|
||||
*
|
||||
* @param key
|
||||
* @param listener
|
||||
*/
|
||||
public void registerListener(String key, MonitoringListener<V> listener) {
|
||||
List<MonitoringListener<V>> list = listeners.get(key);
|
||||
if (list == null) {
|
||||
list = new CopyOnWriteArrayList<MonitoringListener<V>>();
|
||||
listeners.put(key, list);
|
||||
}
|
||||
list.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given listener for the given key.
|
||||
*
|
||||
* @param key
|
||||
* @param listener
|
||||
*/
|
||||
public void unregisterListener(String key, MonitoringListener<V> listener) {
|
||||
List<MonitoringListener<V>> list = listeners.get(key);
|
||||
if (list != null) {
|
||||
int index = list.indexOf(listener);
|
||||
if (index != -1)
|
||||
list.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* system-wide stuff
|
||||
*/
|
||||
private static boolean monitoringEnabled = false;
|
||||
|
||||
/**
|
||||
* enables monitoring for the whole system
|
||||
*/
|
||||
public static void enable() {
|
||||
monitoringEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the monitoringEnabled
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
return monitoringEnabled;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user