<commit_before>/* Copyright (c) 2013, <NAME>
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include "tfileaiologger.h"<commit_msg>added async I/O file writer for Windows.<commit_after>/* Copyright (c) 2013, <NAME>
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include "tfileaiowriter.h"
#include <QList>
#include <windows.h>


typedef struct
{
    char *aio_buf;
    int aio_nbytes;
    OVERLAPPED aio_overlap;
} aiobuf_t;


class TFileAioWriterData
{
public:
    mutable QMutex mutex;
    QString fileName;
    HANDLE fileHandle;
    QList<aiobuf_t *> syncBuffer;

    TFileAioWriterData() : mutex(QMutex::Recursive), fileName(), fileHandle(INVALID_HANDLE_VALUE), syncBuffer() { }
    void clearSyncBuffer();
};


void TFileAioWriterData::clearSyncBuffer()
{
    for (QListIterator<aiobuf_t *> it(syncBuffer); it.hasNext(); ) {
        aiobuf_t *ab = it.next();
        delete (char *)ab->aio_buf;
        delete ab;
    }
    syncBuffer.clear();
}

/*!
  Constructor.
 */
TFileAioWriter::TFileAioWriter(const QString &name)
    : d(new TFileAioWriterData)
{
    d->fileName = name;
}


TFileAioWriter::~TFileAioWriter()
{
    close();
    delete d;
}


bool TFileAioWriter::open()
{
    QMutexLocker locker(&d->mutex);

    if (d->fileHandle == INVALID_HANDLE_VALUE) {
        if (d->fileName.isEmpty())
            return false;

        d->fileHandle = CreateFile((const wchar_t*)d->fileName.utf16(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
        if (d->fileHandle == INVALID_HANDLE_VALUE) {
            //tSystemError("file open failed: %s", qPrintable(d->fileName));
        }
    }

    return (d->fileHandle != INVALID_HANDLE_VALUE);
}


void TFileAioWriter::close()
{
    QMutexLocker locker(&d->mutex);

    flush();

    if (d->fileHandle != INVALID_HANDLE_VALUE) {
        CloseHandle(d->fileHandle);
    }
    d->fileHandle = INVALID_HANDLE_VALUE;
}


bool TFileAioWriter::isOpen() const
{
    return (d->fileHandle != INVALID_HANDLE_VALUE);
}


int TFileAioWriter::write(const char *data, int length)
{
    QMutexLocker locker(&d->mutex);

    if (!isOpen()) {
        return -1;
    }

    // check whether last writing is finished
    if (d->syncBuffer.count() > 0) {
        aiobuf_t *lastab = d->syncBuffer.last();
        if (HasOverlappedIoCompleted(&lastab->aio_overlap)) {
            d->clearSyncBuffer();
        }
    }

    aiobuf_t *ab = new aiobuf_t;
    memset(ab, 0, sizeof(aiobuf_t));

    ab->aio_nbytes = length;
    ab->aio_buf = new char[length];
    ab->aio_overlap.Offset = 0xFFFFFFFF;
    ab->aio_overlap.OffsetHigh = 0xFFFFFFFF;
    memcpy((void *)ab->aio_buf, data, length);

    DWORD dwWritten;
    BOOL res = WriteFile(d->fileHandle, ab->aio_buf, (DWORD)length, &dwWritten, &ab->aio_overlap);

    if (!res) {
        delete (char *)ab->aio_buf;
        delete ab;

        close();
        return -1;
    }

    d->syncBuffer << ab;
    return (int)dwWritten;
}


void TFileAioWriter::flush()
{
    QMutexLocker locker(&d->mutex);

    FlushFileBuffers(d->fileHandle);
    d->clearSyncBuffer();
}

void TFileAioWriter::setFileName(const QString &name)
{
    QMutexLocker locker(&d->mutex);

    if (isOpen()) {
        close();
    }
    d->fileName = name;
}


QString TFileAioWriter::fileName() const
{
    QMutexLocker locker(&d->mutex);
    return d->fileName;
}
{'fraction_non_alphanumeric': 0.1350828729281768, 'fraction_numerical': 0.004419889502762431, 'mean_word_length': 3.2006960556844546, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '1045831', 'n_tokens_mistral': 1300, 'n_tokens_neox': 1245, 'n_words': 271}