<commit_before>/* For lseek64() */
#define _LARGEFILE64_SOURCE

#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include <mycpp/native_async_file.h>
#include <mycpp/util.h>
#include <mycpp/io.h>

namespace MyCpp {

void
NativeAsyncFile::notifyError ()
{
    {
      MutexLock state_lock (state_mutex);

	is_error = true;
    }

    fireError ();
}

IOResult
NativeAsyncFile::read (MemoryDesc const &mem,
		       Size *nread)
    throw (IOException,
	   InternalException)
{
    if (nread != NULL)
	*nread = 0;

    if (mem.getMemory () == NULL ||
	mem.getLength () == 0)
    {
	return IOResultNormal;
    }

    ssize_t ret;

    /* According to POSIX, if we pass a value larger than SSIZE_MAX
     * to read, then the result is implementation-defined. */
    Size len;
    if (mem.getLength () > SSIZE_MAX)
	len = SSIZE_MAX;
    else
	len = mem.getLength ();

    rw_lock.readerLock ();
    if (fd == -1) {
	rw_lock.readerUnlock ();
	throw InternalException ();
    }

    ret = ::read (fd, mem.getMemory (), (size_t) len);
    rw_lock.readerUnlock ();

    if (ret == -1) {
	if (errno == EAGAIN || errno == EWOULDBLOCK) {
	    fireNeedInput (true);
	    return IOResultAgain;
	}

	if (errno == EINTR)
	    return IOResultNormal;

	throw IOException (errnoToString (errno));
    } else
    if (ret < 0) {
	throw IOException ();
    } else
    if (ret == 0) {
	return IOResultEof;
    }

    if ((Size) ret > len)
	throw InternalException (String::forData ("Unexpectedly large return value from read()"));

    if (nread != NULL)
	*nread = (Size) ret;

    return IOResultNormal;
}

IOResult
NativeAsyncFile::write (ConstMemoryDesc const &mem,
			Size *nwritten)
    throw (IOException,
	   InternalException)
{
    if (nwritten != NULL)
	*nwritten = 0;

    if (mem.getMemory () == NULL ||
	mem.getLength () == 0)
    {
	return IOResultNormal;
    }

    ssize_t ret;

    /* According to POSIX, if we pass a value larger than SSIZE_MAX
     * to write, then the result is implementation-defined. */
    Size len;
    if (mem.getLength () > SSIZE_MAX)
	len = SSIZE_MAX;
    else
	len = mem.getLength ();

    rw_lock.readerLock ();
    if (fd == -1) {
	rw_lock.readerUnlock ();
	throw InternalException ();
    }

    ret = ::write (fd, mem.getMemory (), (size_t) len);
    rw_lock.readerUnlock ();

    if (ret == -1) {
	if (errno == EAGAIN || errno == EWOULDBLOCK) {
	    fireNeedOutput (true);
	    return IOResultAgain;
	}

	if (errno == EINTR)
	    return IOResultNormal;

	if (errno == EPIPE)
	    return IOResultEof;

      /* DEBUG */
	errf->print ("MyCpp.NativeAsyncFile.write: ret == -1").pendl ();
      /* (DEBUG) */

	throw IOException (errnoToString (errno));
    } else
    if (ret < 0) {
      /* DEBUG */
	errf->print ("MyCpp.NativeAsyncFile.write: ret < 0").pendl ();
      /* (DEBUG) */

	throw IOException ();
    }

    if ((Size) ret > len)
	throw InternalException (String::forData ("Unexpectedly large return value from write()"));

    if (nwritten != NULL)
	*nwritten = (Size) ret;

    return IOResultNormal;
}

void
NativeAsyncFile::seek (Int64      offset,
		       SeekOrigin origin)
    throw (IOException,
	   InternalException)
{
    int whence = 0;

    switch (origin) {
    case SeekOrigin::SeekBeg:
	whence = SEEK_SET;
	break;
    case SeekOrigin::SeekCur:
	whence = SEEK_CUR;
	break;
    case SeekOrigin::SeekEnd:
	whence = SEEK_END;
	break;
    }

    rw_lock.readerLock ();
    if (fd == -1) {
	rw_lock.readerUnlock ();
	throw InternalException ();
    }

    /* NOTE: lseek64() seems to be glibc-specific. */
    if (lseek64 (fd, (off64_t) offset, whence) == (off64_t) -1) {
	rw_lock.readerUnlock ();<commit_msg>Consider lseek64() to be Linux-specific.<commit_after>#ifdef __linux__
/* For lseek64() */
#define _LARGEFILE64_SOURCE
#endif

#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include <mycpp/native_async_file.h>
#include <mycpp/util.h>
#include <mycpp/io.h>

namespace MyCpp {

void
NativeAsyncFile::notifyError ()
{
    {
      MutexLock state_lock (state_mutex);

	is_error = true;
    }

    fireError ();
}

IOResult
NativeAsyncFile::read (MemoryDesc const &mem,
		       Size *nread)
    throw (IOException,
	   InternalException)
{
    if (nread != NULL)
	*nread = 0;

    if (mem.getMemory () == NULL ||
	mem.getLength () == 0)
    {
	return IOResultNormal;
    }

    ssize_t ret;

    /* According to POSIX, if we pass a value larger than SSIZE_MAX
     * to read, then the result is implementation-defined. */
    Size len;
    if (mem.getLength () > SSIZE_MAX)
	len = SSIZE_MAX;
    else
	len = mem.getLength ();

    rw_lock.readerLock ();
    if (fd == -1) {
	rw_lock.readerUnlock ();
	throw InternalException ();
    }

    ret = ::read (fd, mem.getMemory (), (size_t) len);
    rw_lock.readerUnlock ();

    if (ret == -1) {
	if (errno == EAGAIN || errno == EWOULDBLOCK) {
	    fireNeedInput (true);
	    return IOResultAgain;
	}

	if (errno == EINTR)
	    return IOResultNormal;

	throw IOException (errnoToString (errno));
    } else
    if (ret < 0) {
	throw IOException ();
    } else
    if (ret == 0) {
	return IOResultEof;
    }

    if ((Size) ret > len)
	throw InternalException (String::forData ("Unexpectedly large return value from read()"));

    if (nread != NULL)
	*nread = (Size) ret;

    return IOResultNormal;
}

IOResult
NativeAsyncFile::write (ConstMemoryDesc const &mem,
			Size *nwritten)
    throw (IOException,
	   InternalException)
{
    if (nwritten != NULL)
	*nwritten = 0;

    if (mem.getMemory () == NULL ||
	mem.getLength () == 0)
    {
	return IOResultNormal;
    }

    ssize_t ret;

    /* According to POSIX, if we pass a value larger than SSIZE_MAX
     * to write, then the result is implementation-defined. */
    Size len;
    if (mem.getLength () > SSIZE_MAX)
	len = SSIZE_MAX;
    else
	len = mem.getLength ();

    rw_lock.readerLock ();
    if (fd == -1) {
	rw_lock.readerUnlock ();
	throw InternalException ();
    }

    ret = ::write (fd, mem.getMemory (), (size_t) len);
    rw_lock.readerUnlock ();

    if (ret == -1) {
	if (errno == EAGAIN || errno == EWOULDBLOCK) {
	    fireNeedOutput (true);
	    return IOResultAgain;
	}

	if (errno == EINTR)
	    return IOResultNormal;

	if (errno == EPIPE)
	    return IOResultEof;

      /* DEBUG */
	errf->print ("MyCpp.NativeAsyncFile.write: ret == -1").pendl ();
      /* (DEBUG) */

	throw IOException (errnoToString (errno));
    } else
    if (ret < 0) {
      /* DEBUG */
	errf->print ("MyCpp.NativeAsyncFile.write: ret < 0").pendl ();
      /* (DEBUG) */

	throw IOException ();
    }

    if ((Size) ret > len)
	throw InternalException (String::forData ("Unexpectedly large return value from write()"));

    if (nwritten != NULL)
	*nwritten = (Size) ret;

    return IOResultNormal;
}

void
NativeAsyncFile::seek (Int64      offset,
		       SeekOrigin origin)
    throw (IOException,
	   InternalException)
{
    int whence = 0;

    switch (origin) {
    case SeekOrigin::SeekBeg:
	whence = SEEK_SET;
	break;
    case SeekOrigin::SeekCur:
	whence = SEEK_CUR;
	break;
    case SeekOrigin::SeekEnd:
	whence = SEEK_END;
	break;
    }

    rw_lock.readerLock ();
    if (fd == -1) {
	rw_lock.readerUnlock ();
	throw InternalException ();
    }

#ifdef __linux__
    /* NOTE: lseek64() seems to be glibc-specific. */
    if (lseek64 (fd, (off64_t) offset, whence) == (off64_t) -1) {
#else
    if (lseek (fd, (off_t) offset, whence) == (off_t) -1) {
#endif
	rw_lock.readerUnlock ();
{'fraction_non_alphanumeric': 0.14191766407996842, 'fraction_numerical': 0.008286202814678416, 'mean_word_length': 2.8579401319127347, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1524644', 'n_tokens_mistral': 2860, 'n_tokens_neox': 2685, 'n_words': 688}