On Fri, Jul 1, 2022 at 12:00 AM Yann Ylavic <ylavic....@gmail.com> wrote:
>
> On Thu, Jun 30, 2022 at 7:28 PM <i...@apache.org> wrote:
> >
> > Author: ivan
> > Date: Thu Jun 30 17:28:50 2022
> > New Revision: 1902378
> >
> > URL: http://svn.apache.org/viewvc?rev=1902378&view=rev
> > Log:
> > On 1.8.x branch: Merge r1806299, r1806301, r1806308, r1806610:
> >   *) apr_file_write: Optimize large writes to buffered files on
> >      Windows.
> []
> >
> > --- apr/apr/branches/1.8.x/file_io/win32/readwrite.c (original)
> > +++ apr/apr/branches/1.8.x/file_io/win32/readwrite.c Thu Jun 30 17:28:50 
> > 2022
> > @@ -247,6 +247,91 @@ APR_DECLARE(apr_status_t) apr_file_read(
> >      return rv;
> >  }
> >
> > +/* Helper function that adapts WriteFile() to apr_size_t instead
> > + * of DWORD. */
> > +static apr_status_t write_helper(HANDLE filehand, const char *buf,
> > +                                 apr_size_t len, apr_size_t *pwritten)
> > +{
> > +    apr_size_t remaining = len;
> > +
> > +    *pwritten = 0;
> > +    do {
> > +        DWORD to_write;
> > +        DWORD written;
> > +
> > +        if (remaining > APR_DWORD_MAX) {
> > +            to_write = APR_DWORD_MAX;
> > +        }
> > +        else {
> > +            to_write = (DWORD)remaining;
> > +        }
> > +
> > +        if (!WriteFile(filehand, buf, to_write, &written, NULL)) {
> > +            *pwritten += written;
> > +            return apr_get_os_error();
> > +        }
> > +
> > +        *pwritten += written;
> > +        remaining -= written;
> > +        buf += written;
> > +    } while (remaining);
>
> So there's no writev() like syscall on Windows (something that
> provides atomicity)?

I found WriteFileGather
(https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefilegather).
Maybe it can help with some logic à la apr_socket_sendv()?

> I would stop the loop on written < to_write at least, apr_file_write()
> should be prepared to get a short/partial write (for whatever reason),
> or otherwise use apr_file_write_full().
>
> > +
> > +    return APR_SUCCESS;
> > +}
> > +
> > +static apr_status_t write_buffered(apr_file_t *thefile, const char *buf,
> > +                                   apr_size_t len, apr_size_t *pwritten)
> > +{
> > +    apr_status_t rv;
> > +
> > +    if (thefile->direction == 0) {
> > +        /* Position file pointer for writing at the offset we are 
> > logically reading from */
> > +        apr_off_t offset = thefile->filePtr - thefile->dataRead + 
> > thefile->bufpos;
> > +        DWORD offlo = (DWORD)offset;
> > +        LONG offhi = (LONG)(offset >> 32);
> > +        if (offset != thefile->filePtr)
> > +            SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN);
> > +        thefile->bufpos = thefile->dataRead = 0;
> > +        thefile->direction = 1;
> > +    }
> > +
> > +    *pwritten = 0;
> > +
> > +    while (len > 0) {
> > +        if (thefile->bufpos == thefile->bufsize) { /* write buffer is full 
> > */
> > +            rv = apr_file_flush(thefile);
> > +            if (rv) {
> > +                return rv;
> > +            }
> > +        }
> > +        /* If our buffer is empty, and we cannot fit the remaining chunk
> > +         * into it, write the chunk with a single syscall and return.
> > +         */
> > +        if (thefile->bufpos == 0 && len > thefile->bufsize) {
> > +            apr_size_t written;
> > +
> > +            rv = write_helper(thefile->filehand, buf, len, &written);
> > +            thefile->filePtr += written;
> > +            *pwritten += written;
> > +            return rv;
> > +        }
> > +        else {
> > +            apr_size_t blocksize = len;
> > +
> > +            if (blocksize > thefile->bufsize - thefile->bufpos) {
> > +                blocksize = thefile->bufsize - thefile->bufpos;
> > +            }
> > +            memcpy(thefile->buffer + thefile->bufpos, buf, blocksize);
> > +            thefile->bufpos += blocksize;
> > +            buf += blocksize;
> > +            len -= blocksize;
> > +            *pwritten += blocksize;
> > +        }
> > +    }
>
> Likewise.
>
> > +
> > +    return APR_SUCCESS;
> > +}
>
>
> Regards;
> Yann.

Reply via email to