On the javahl-1.7-extensions branch: Synced JavaHL with trunk up to r1520245.
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/javahl-1.7-extensions@1520549 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subversion/bindings/javahl/native/CreateJ.cpp b/subversion/bindings/javahl/native/CreateJ.cpp
index ee3bf5b..2539e65 100644
--- a/subversion/bindings/javahl/native/CreateJ.cpp
+++ b/subversion/bindings/javahl/native/CreateJ.cpp
@@ -835,7 +835,13 @@
jlong jhunkModifiedStart = wcNotify->hunk_modified_start;
jlong jhunkModifiedLength = wcNotify->hunk_modified_length;
jlong jhunkMatchedLine = wcNotify->hunk_matched_line;
- jint jhunkFuzz = wcNotify->hunk_fuzz;
+ jint jhunkFuzz = static_cast<jint>(wcNotify->hunk_fuzz);
+ if (jhunkFuzz < 0 || jhunkFuzz != wcNotify->hunk_fuzz)
+ {
+ env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
+ "Overflow converting C svn_linenum_t to Java int");
+ POP_AND_RETURN_NULL;
+ }
// call the Java method
jobject jInfo = env->NewObject(clazz, midCT, jPath, jAction,
diff --git a/subversion/bindings/javahl/native/JNIUtil.cpp b/subversion/bindings/javahl/native/JNIUtil.cpp
index 8f520c4..39e9312 100644
--- a/subversion/bindings/javahl/native/JNIUtil.cpp
+++ b/subversion/bindings/javahl/native/JNIUtil.cpp
@@ -36,6 +36,7 @@
#include <apr_general.h>
#include <apr_lib.h>
#include <apr_file_info.h>
+#include <apr_time.h>
#include "svn_pools.h"
#include "svn_fs.h"
@@ -106,6 +107,93 @@
return true;
}
+namespace
+{
+struct GlobalInitGuard
+{
+ enum InitState
+ {
+ state_null,
+ state_init,
+ state_done,
+ state_error
+ };
+
+ GlobalInitGuard()
+ : m_finished(false),
+ m_state(InitState(svn_atomic_cas(&m_global_state,
+ state_init, state_null)))
+ {
+ switch (m_state)
+ {
+ case state_null:
+ // This thread won the initialization contest.
+ break;
+
+ case state_done:
+ // The library is already initialized.
+ break;
+
+ case state_init:
+ // Another thread is currently initializing the
+ // library. Spin and wait for it to finish, with exponential
+ // backoff, but no longer than half a second.
+ for (unsigned shift = 0;
+ m_state == state_init && shift < 8;
+ ++shift)
+ {
+ apr_sleep((APR_USEC_PER_SEC / 1000) << shift);
+ m_state = InitState(svn_atomic_cas(&m_global_state,
+ state_null, state_null));
+ }
+ if (m_state == state_init)
+ // The initialization didn't complete in half a second,
+ // which probably implies a thread crash or a deadlock.
+ m_state = state_error;
+ break;
+
+ default:
+ // Error state, or unknown state. In any case, do not continue.
+ m_state = state_error;
+ }
+ }
+
+ ~GlobalInitGuard()
+ {
+ // Signal the end of the library intialization if we're the
+ // initializing thread.
+ if (m_finished && m_state == state_null)
+ {
+ SVN_ERR_ASSERT_NO_RETURN(
+ state_init == svn_atomic_cas(&m_global_state,
+ state_done, state_init));
+ }
+ }
+
+ bool done() const
+ {
+ return (m_state == state_done);
+ }
+
+ bool error() const
+ {
+ return (m_state == state_error);
+ }
+
+ void finish()
+ {
+ m_finished = true;
+ }
+
+private:
+ bool m_finished;
+ InitState m_state;
+ static volatile svn_atomic_t m_global_state;
+};
+volatile svn_atomic_t
+GlobalInitGuard::m_global_state = GlobalInitGuard::state_null;
+} // anonymous namespace
+
/**
* Initialize the environment for all requests.
* @param env the JNI environment for this request
@@ -113,16 +201,10 @@
bool JNIUtil::JNIGlobalInit(JNIEnv *env)
{
// This method has to be run only once during the run a program.
- static volatile svn_atomic_t once = 0;
- svn_atomic_t done = svn_atomic_cas(&once, 1, 0);
- if (done)
+ GlobalInitGuard guard;
+ if (guard.done())
return true;
-
- // Do not run this part more than one time. This leaves a small
- // time window when two threads create their first SVNClient and
- // SVNAdmin at the same time, but I do not see a better option
- // without APR already initialized
- if (g_inInit)
+ else if (guard.error())
return false;
g_inInit = true;
@@ -282,6 +364,8 @@
g_initEnv = NULL;
g_inInit = false;
+
+ guard.finish();
return true;
}
@@ -579,7 +663,7 @@
POP_AND_RETURN_NOTHING();
const jsize stSize = static_cast<jsize>(newStackTrace.size());
- if (stSize != newStackTrace.size())
+ if (stSize < 0 || stSize != newStackTrace.size())
{
env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
"Overflow converting C size_t to JNI jsize");
diff --git a/subversion/bindings/javahl/native/RemoteSession.cpp b/subversion/bindings/javahl/native/RemoteSession.cpp
index 0ca212c..60c8739 100644
--- a/subversion/bindings/javahl/native/RemoteSession.cpp
+++ b/subversion/bindings/javahl/native/RemoteSession.cpp
@@ -1073,8 +1073,10 @@
apr_array_header_t* prop_diffs,
apr_pool_t* scratch_pool)
{
- *delta_handler = svn_delta_noop_window_handler;
- *delta_handler_baton = NULL;
+ if (delta_handler)
+ *delta_handler = svn_delta_noop_window_handler;
+ if (delta_handler_baton)
+ *delta_handler_baton = NULL;
FileRevisionHandler* const self =
static_cast<FileRevisionHandler*>(baton);
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_NativeResources.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_NativeResources.cpp
index 9705304..3bf69a4 100644
--- a/subversion/bindings/javahl/native/org_apache_subversion_javahl_NativeResources.cpp
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_NativeResources.cpp
@@ -28,11 +28,11 @@
#include "JNIUtil.h"
#include "../include/org_apache_subversion_javahl_NativeResources.h"
-JNIEXPORT void JNICALL
+JNIEXPORT jboolean JNICALL
Java_org_apache_subversion_javahl_NativeResources_initNativeLibrary
(JNIEnv *env, jclass jclazz)
{
// No usual JNIEntry here, as the prerequisite native library
// initialization is performed here.
- JNIUtil::JNIGlobalInit(env);
+ return jboolean(JNIUtil::JNIGlobalInit(env));
}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNConfig.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNConfig.java
index 12206e1..2c7e5ed 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNConfig.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNConfig.java
@@ -112,19 +112,19 @@
public static final String HTTP_CHUNKED_REQUESTS = "http-chunked-requests";
/**
- * "true" value in configuraition. One of the values returned by
+ * "true" value in configuration. One of the values returned by
* {@link Category#getYesNoAsk}.
*/
public static final String TRUE = "TRUE";
/**
- * "false" value in configuraition. One of the values returned by
+ * "false" value in configuration. One of the values returned by
* {@link Category#getYesNoAsk}.
*/
public static final String FALSE = "FALSE";
/**
- * "ask" value in configuraition. One of the values returned by
+ * "ask" value in configuration. One of the values returned by
* {@link Category#getYesNoAsk}.
*/
public static final String ASK = "ASK";
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
index 608e6a2..50afd49 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
@@ -261,8 +261,7 @@
* <code>sourceRelativePath</code> at the start of the whole edit
* and<code>sourceRelativePath</code> at
* <code>sourceRevision</code> must lie within the same node-rev
- * (aka history-segment). This is just like the #delete() and
- * #rotate().
+ * (aka history-segment). This is just like the #delete().
* <p>
* For a description of <code>replacesRevision</code>, see #addFile().
*
@@ -274,42 +273,6 @@
long replacesRevision)
throws ClientException;
-// Not implemented in the native API
-// /**
-// * Perform a rotation among multiple nodes in the target tree.
-// * <p>
-// * The <code>elements</code> list specifies the nodes in the tree
-// * which are located at a path and expected to be at a specific
-// * revision. These nodes are simultaneously moved in a rotation
-// * pattern. For example, the node at index 0
-// * <code>elements</code> will be moved to the relative path
-// * specified at index 1 of <code>elements</code>. The node at
-// * index 1 will be moved to the location at index 2. The node at
-// * index N-1 will be moved to the relative path specified at index 0.
-// * <p>
-// * The simplest form of this operation is to swap nodes A and
-// * B. One may think to move A to a temporary location T, then move
-// * B to A, then move T to B. However, this last move violations
-// * the Once Rule by moving T (which had already by edited by the
-// * move from A). In order to keep the restrictions against
-// * multiple moves of a single node, the rotation operation is
-// * needed for certain types of tree edits.
-// *
-// * @throws ClientException
-// */
-// void rotate(Iterable<RotatePair> elements) throws ClientException;
-//
-// public static final class RotatePair
-// {
-// public RotatePair(String relativePath, long revision)
-// {
-// this.relativePath = relativePath;
-// this.revision = revision;
-// }
-// public final String relativePath;
-// public final long revision;
-// }
-
/**
* Signal that the edit has been completed successfully.
* After this method is called, the editor is considered closed.
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java
index 3317bd3..1083520 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java
@@ -129,7 +129,9 @@
*/
private static final void init()
{
- initNativeLibrary();
+ if (!initNativeLibrary())
+ throw new LinkageError("Native library initialization failed");
+
version = new Version();
if (!version.isAtLeast(1, 7, 0))
{
@@ -141,5 +143,5 @@
/**
* Initialize the native library layer.
*/
- private static native void initNativeLibrary();
+ private static native boolean initNativeLibrary();
}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
index 9bbef67..450f14c 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
@@ -131,9 +131,6 @@
notimplemented("move");
}
-// public void rotate(Iterable<RotatePair> elements)
-// throws ClientException;
-
public void complete() throws ClientException
{
notimplemented("complete");