Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 92845 invoked from network); 30 Sep 2009 18:25:36 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 30 Sep 2009 18:25:36 -0000 Received: (qmail 68015 invoked by uid 500); 30 Sep 2009 18:25:36 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 67945 invoked by uid 500); 30 Sep 2009 18:25:36 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 67936 invoked by uid 99); 30 Sep 2009 18:25:36 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Sep 2009 18:25:36 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Sep 2009 18:25:31 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id BE8632388908; Wed, 30 Sep 2009 18:24:39 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r820372 - /commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c Date: Wed, 30 Sep 2009 18:24:39 -0000 To: commits@commons.apache.org From: mturk@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090930182439.BE8632388908@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: mturk Date: Wed Sep 30 18:24:39 2009 New Revision: 820372 URL: http://svn.apache.org/viewvc?rev=820372&view=rev Log: Implement win32 write methods Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c?rev=820372&r1=820371&r2=820372&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c Wed Sep 30 18:24:39 2009 @@ -286,33 +286,18 @@ return fdo; } -ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock0)(ACR_JNISTDARGS, - jint file, - jint type) +static int do_lock(acr_file_t *f, DWORD flags) { - OVERLAPPED opp; - DWORD flags = 0; - acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); - - if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) - return ACR_EFTYPE; - if (IS_INVALID_HANDLE(f)) - return ACR_EBADF; - - if (type & ACR_FLOCK_NONBLOCK) - flags = LOCKFILE_FAIL_IMMEDIATELY; - else if (f->blocking == BLK_OFF) { + if (f->blocking == BLK_OFF) { if (IS_INVALID_HANDLE(f->overlap.hEvent)) { f->overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (IS_INVALID_HANDLE(f->overlap.hEvent)) return ACR_GET_OS_ERROR(); } } - if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED) - flags |= LOCKFILE_EXCLUSIVE_LOCK; f->overlap.Offset = 0; f->overlap.OffsetHigh = 0; - if (!LockFileEx(f->fd, flags, 0, 0xFFFFFFFF, 0xFFFFFFFF, &opp)) { + if (!LockFileEx(f->fd, flags, 0, 0xFFFFFFFF, 0xFFFFFFFF, &f->overlap)) { int rc = ACR_GET_OS_ERROR(); if (rc == ERROR_IO_PENDING) { do { @@ -347,6 +332,27 @@ } else return 0; + +} + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock0)(ACR_JNISTDARGS, + jint file, + jint type) +{ + DWORD flags = 0; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) + return ACR_EFTYPE; + if (IS_INVALID_HANDLE(f)) + return ACR_EBADF; + + if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED) + flags |= LOCKFILE_EXCLUSIVE_LOCK; + if (type & ACR_FLOCK_NONBLOCK) + flags = LOCKFILE_FAIL_IMMEDIATELY; + + return do_lock(f, flags); } ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock1)(ACR_JNISTDARGS, @@ -356,7 +362,6 @@ jlong len) { LARGE_INTEGER lii; - OVERLAPPED opp; DWORD flags = 0; acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); @@ -367,20 +372,20 @@ if (type & ACR_FLOCK_NONBLOCK) flags = LOCKFILE_FAIL_IMMEDIATELY; - else if (f->blocking == BLK_OFF) { + if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED) + flags |= LOCKFILE_EXCLUSIVE_LOCK; + if (f->blocking == BLK_OFF) { if (IS_INVALID_HANDLE(f->overlap.hEvent)) { f->overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (IS_INVALID_HANDLE(f->overlap.hEvent)) return ACR_GET_OS_ERROR(); } } - if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED) - flags |= LOCKFILE_EXCLUSIVE_LOCK; f->overlap.Offset = (DWORD)(off); f->overlap.OffsetHigh = (DWORD)(off >> 32); lii.QuadPart = len; - if (!LockFileEx(f->fd, flags, 0, lii.LowPart, lii.HighPart, &opp)) { + if (!LockFileEx(f->fd, flags, 0, lii.LowPart, lii.HighPart, &f->overlap)) { int rc = ACR_GET_OS_ERROR(); if (rc == ERROR_IO_PENDING) { do { @@ -953,7 +958,7 @@ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0); return -1; } - if ((po + cs) > pl) { + if ((po + cs) > (DWORD)pl) { ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0); return -1; } @@ -1137,3 +1142,663 @@ return f->err == ACR_TIMEUP ? 0 : -1; return -1; } + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, write0)(ACR_JNISTDARGS, + jint file, + jint b) +{ + unsigned char c = (unsigned char)(b & 0xFF); + DWORD rc; + DWORD wr = 0; + int locked = 0; + LPOVERLAPPED lpo = NULL; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return -1; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return -1; + } + if (f->flags & ACR_FOPEN_APPEND) { + LARGE_INTEGER os; + LARGE_INTEGER op; + + EnterCriticalSection(&f->lock); + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + LeaveCriticalSection(&f->lock); + return -1; + } + /* Set the position to the file end + */ + os.QuadPart = 0; + op.QuadPart = 0; + if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) { + ACR_THROW_IO_ERRNO(); + LeaveCriticalSection(&f->lock); + return -1; + } + f->pos = op.QuadPart; + locked = 1; + } + if (f->blocking == BLK_OFF) { + lpo = &f->overlap; + if (IS_INVALID_HANDLE(lpo->hEvent)) + lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (IS_INVALID_HANDLE(lpo->hEvent)) { + ACR_THROW_IO_ERRNO(); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + lpo->Offset = (DWORD)(f->pos); + lpo->OffsetHigh = (DWORD)(f->pos >> 32); + } + f->err = 0; + if (WriteFile(f->fd, &c, 1, &wr, lpo)) { + /* All done. Update the position and return + */ + if (wr) + f->pos += wr; + goto finally; + } + switch (f->err = GetLastError()) { + case ERROR_IO_PENDING: + if ((f->err = overlapped_wait(f, &wr)) == 0) { + if (wr) { + f->pos += wr; + goto finally; + } + } + break; + default: + break; + } + +finally: + if (locked) + LeaveCriticalSection(&f->lock); + if (wr) + return (jint)wr; + if (f->err) + return f->err == ACR_TIMEUP ? 0 : -1; + return -1; +} + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, write1)(ACR_JNISTDARGS, + jint file, + jbyteArray buf, + jint off, + jint len) +{ + jbyte *bb; + DWORD rc; + DWORD po = (DWORD)off; + DWORD cs = (DWORD)len; + DWORD wr = 0; + int locked = 0; + LPOVERLAPPED lpo = NULL; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return -1; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return -1; + } + + if (f->flags & ACR_FOPEN_APPEND) { + LARGE_INTEGER os; + LARGE_INTEGER op; + + EnterCriticalSection(&f->lock); + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + LeaveCriticalSection(&f->lock); + return -1; + } + /* Set the position to the file end + */ + os.QuadPart = 0; + op.QuadPart = 0; + if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) { + ACR_THROW_IO_ERRNO(); + LeaveCriticalSection(&f->lock); + return -1; + } + f->pos = op.QuadPart; + locked = 1; + } + if (f->blocking == BLK_OFF) { + lpo = &f->overlap; + if (IS_INVALID_HANDLE(lpo->hEvent)) + lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (IS_INVALID_HANDLE(lpo->hEvent)) { + ACR_THROW_IO_ERRNO(); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + lpo->Offset = (DWORD)(f->pos); + lpo->OffsetHigh = (DWORD)(f->pos >> 32); + } + + bb = (*_E)->GetByteArrayElements(_E, buf, NULL); + if (!bb) { + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + f->err = 0; + if (WriteFile(f->fd, bb + po, cs, &wr, lpo)) { + /* All done. Update the position and return + */ + if (wr) + f->pos += wr; + goto finally; + } + switch (f->err = GetLastError()) { + case ERROR_IO_PENDING: + if ((f->err = overlapped_wait(f, &wr)) == 0) { + if (wr) { + f->pos += wr; + goto finally; + } + } + break; + default: + break; + } + +finally: + if (locked) + LeaveCriticalSection(&f->lock); + (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT); + if (wr) + return (jint)wr; + if (f->err) + return f->err == ACR_TIMEUP ? 0 : -1; + return -1; +} + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, write2)(ACR_JNISTDARGS, + jint file, + jobject ptr, + jlong off, + jlong len) +{ + size_t pl; + jbyte *pb; + DWORD rc; + DWORD po = (DWORD)off; + DWORD cs = (DWORD)len; + DWORD wr = 0; + int locked = 0; + LPOVERLAPPED lpo = NULL; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return -1; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return -1; + } + if (f->flags & ACR_FOPEN_APPEND) { + LARGE_INTEGER os; + LARGE_INTEGER op; + + EnterCriticalSection(&f->lock); + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + LeaveCriticalSection(&f->lock); + return -1; + } + /* Set the position to the file end + */ + os.QuadPart = 0; + op.QuadPart = 0; + if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) { + ACR_THROW_IO_ERRNO(); + LeaveCriticalSection(&f->lock); + return -1; + } + f->pos = op.QuadPart; + locked = 1; + } + if (f->blocking == BLK_OFF) { + lpo = &f->overlap; + if (IS_INVALID_HANDLE(lpo->hEvent)) + lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (IS_INVALID_HANDLE(lpo->hEvent)) { + ACR_THROW_IO_ERRNO(); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + lpo->Offset = (DWORD)(f->pos); + lpo->OffsetHigh = (DWORD)(f->pos >> 32); + } + pb = (jbyte *)ACR_PointerGet(_E, ptr, &pl); + if (!pb) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + if ((po + cs) > (DWORD)pl) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + + f->err = 0; + if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) { + /* All done. Update the position and return + */ + if (wr) + f->pos += wr; + goto finally; + } + switch (f->err = GetLastError()) { + case ERROR_IO_PENDING: + if ((f->err = overlapped_wait(f, &wr)) == 0) { + if (wr) { + f->pos += wr; + goto finally; + } + } + break; + default: + break; + } + +finally: + if (locked) + LeaveCriticalSection(&f->lock); + if (wr) + return (jint)wr; + if (f->err) + return f->err == ACR_TIMEUP ? 0 : -1; + return -1; +} + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, write3)(ACR_JNISTDARGS, + jint file, + jobject dbb, + jlong off, + jlong len) +{ +#if defined(_DEBUG) + DWORD pl; +#endif + jbyte *pb; + DWORD rc; + DWORD po = (DWORD)off; + DWORD cs = (DWORD)len; + DWORD wr = 0; + int locked = 0; + LPOVERLAPPED lpo = NULL; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return -1; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return -1; + } + if (f->flags & ACR_FOPEN_APPEND) { + LARGE_INTEGER os; + LARGE_INTEGER op; + + EnterCriticalSection(&f->lock); + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + LeaveCriticalSection(&f->lock); + return -1; + } + /* Set the position to the file end + */ + os.QuadPart = 0; + op.QuadPart = 0; + if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) { + ACR_THROW_IO_ERRNO(); + LeaveCriticalSection(&f->lock); + return -1; + } + f->pos = op.QuadPart; + locked = 1; + } + if (f->blocking == BLK_OFF) { + lpo = &f->overlap; + if (IS_INVALID_HANDLE(lpo->hEvent)) + lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (IS_INVALID_HANDLE(lpo->hEvent)) { + ACR_THROW_IO_ERRNO(); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + lpo->Offset = (DWORD)(f->pos); + lpo->OffsetHigh = (DWORD)(f->pos >> 32); + } + pb = (jbyte *)(*_E)->GetDirectBufferAddress(_E, dbb); + if (!pb) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } +#if defined(_DEBUG) + pl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, dbb); + if ((po + cs) > pl) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } +#endif + f->err = 0; + if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) { + /* All done. Update the position and return + */ + if (wr) + f->pos += wr; + goto finally; + } + switch (f->err = GetLastError()) { + case ERROR_IO_PENDING: + if ((f->err = overlapped_wait(f, &wr)) == 0) { + if (wr) { + f->pos += wr; + goto finally; + } + } + break; + default: + break; + } + +finally: + if (locked) + LeaveCriticalSection(&f->lock); + if (wr) + return (jint)wr; + if (f->err) + return f->err == ACR_TIMEUP ? 0 : -1; + return -1; +} + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, write4)(ACR_JNISTDARGS, + jint file, + jobjectArray vec, + jint off, + jint len) +{ + DWORD i; + DWORD pl; + DWORD rc; + DWORD wr; + DWORD po = (DWORD)off; + DWORD cs = (DWORD)len; + jbyteArray bae; + jbyte *bab; + DWORD bal; + int locked = 0; + DWORD nbytes = 0; + LPOVERLAPPED lpo = NULL; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return -1; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return -1; + } + + pl = (DWORD)(*_E)->GetArrayLength(_E, vec); + if ((po + cs) > pl) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0); + return -1; + } + if ((*_E)->EnsureLocalCapacity(_E, (jint)(cs * 2))) + return -1; + if (f->flags & ACR_FOPEN_APPEND) { + LARGE_INTEGER os; + LARGE_INTEGER op; + + EnterCriticalSection(&f->lock); + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + LeaveCriticalSection(&f->lock); + return -1; + } + /* Set the position to the file end + */ + os.QuadPart = 0; + op.QuadPart = 0; + if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) { + ACR_THROW_IO_ERRNO(); + LeaveCriticalSection(&f->lock); + return -1; + } + f->pos = op.QuadPart; + locked = 1; + } + if (f->blocking == BLK_OFF) { + lpo = &f->overlap; + if (IS_INVALID_HANDLE(lpo->hEvent)) + lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (IS_INVALID_HANDLE(lpo->hEvent)) { + ACR_THROW_IO_ERRNO(); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + } + + f->err = 0; + for (i = 0; i < cs, f->err == 0; i++) { + bae = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po)); + bal = (DWORD)(*_E)->GetArrayLength(_E, bae); + bab = (*_E)->GetByteArrayElements(_E, bae, NULL); + if (lpo) { + lpo->Offset = (DWORD)(f->pos); + lpo->OffsetHigh = (DWORD)(f->pos >> 32); + } + wr = 0; + if (WriteFile(f->fd, bab, bal, &wr, lpo)) { + /* All done. Update the position and return + */ + if (wr) { + f->pos += wr; + nbytes += wr; + } + } + else { + switch (f->err = GetLastError()) { + case ERROR_IO_PENDING: + if ((f->err = overlapped_wait(f, &wr)) == 0) { + if (wr) { + f->pos += wr; + nbytes += wr; + } + } + break; + default: + break; + } + } + (*_E)->ReleaseByteArrayElements(_E, bae, bab, JNI_ABORT); + } + + if (locked) + LeaveCriticalSection(&f->lock); + if (nbytes) + return (jint)nbytes; + if (f->err) + return f->err == ACR_TIMEUP ? 0 : -1; + return -1; +} + +ACR_IO_EXPORT_DECLARE(jint, FileSystem, write5)(ACR_JNISTDARGS, + jint file, + jobjectArray vec, + jint off, + jint len) +{ + DWORD i; + DWORD pl; + DWORD rc; + DWORD wr; + DWORD po = (DWORD)off; + DWORD cs = (DWORD)len; + jobject bbe; + void *bbb; + DWORD bbl; + int locked = 0; + DWORD nbytes = 0; + LPOVERLAPPED lpo = NULL; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return -1; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return -1; + } + + pl = (DWORD)(*_E)->GetArrayLength(_E, vec); + if ((po + cs) > pl) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0); + return -1; + } + if ((*_E)->EnsureLocalCapacity(_E, (jint)(cs * 2))) + return -1; + if (f->flags & ACR_FOPEN_APPEND) { + LARGE_INTEGER os; + LARGE_INTEGER op; + + EnterCriticalSection(&f->lock); + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + LeaveCriticalSection(&f->lock); + return -1; + } + /* Set the position to the file end + */ + os.QuadPart = 0; + op.QuadPart = 0; + if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) { + ACR_THROW_IO_ERRNO(); + LeaveCriticalSection(&f->lock); + return -1; + } + f->pos = op.QuadPart; + locked = 1; + } + if (f->blocking == BLK_OFF) { + lpo = &f->overlap; + if (IS_INVALID_HANDLE(lpo->hEvent)) + lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (IS_INVALID_HANDLE(lpo->hEvent)) { + ACR_THROW_IO_ERRNO(); + if (locked) + LeaveCriticalSection(&f->lock); + return -1; + } + } + + f->err = 0; + for (i = 0; i < cs, f->err == 0; i++) { + bbe = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po)); + bbl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, bbe); + bbb = (*_E)->GetDirectBufferAddress(_E, bbe); + (*_E)->DeleteLocalRef(_E, bbe); + + if (lpo) { + lpo->Offset = (DWORD)(f->pos); + lpo->OffsetHigh = (DWORD)(f->pos >> 32); + } + wr = 0; + if (WriteFile(f->fd, bbb, bbl, &wr, lpo)) { + /* All done. Update the position and return + */ + if (wr) { + f->pos += wr; + nbytes += wr; + } + } + else { + switch (f->err = GetLastError()) { + case ERROR_IO_PENDING: + if ((f->err = overlapped_wait(f, &wr)) == 0) { + if (wr) { + f->pos += wr; + nbytes += wr; + } + } + break; + default: + break; + } + } + } + + if (locked) + LeaveCriticalSection(&f->lock); + if (nbytes) + return (jint)nbytes; + if (f->err) + return f->err == ACR_TIMEUP ? 0 : -1; + return -1; +}