/***********************************************************************
 *                                                                      *
 *               This software is part of the ast package               *
 *          Copyright (c) 1999-2011 AT&T Intellectual Property          *
 *                      and is licensed under the                       *
 *                 Eclipse Public License, Version 1.0                  *
 *                    by AT&T Intellectual Property                     *
 *                                                                      *
 *                A copy of the License is available at                 *
 *          http://www.eclipse.org/org/documents/epl-v10.html           *
 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
 *                                                                      *
 *              Information and Software Systems Research               *
 *                            AT&T Research                             *
 *                           Florham Park NJ                            *
 *                                                                      *
 *               Glenn Fowler <glenn.s.fowler@gmail.com>                *
 *                                                                      *
 ***********************************************************************/
#include "config_ast.h"  // IWYU pragma: keep

#include <stddef.h>
#include <string.h>

#include "sfio.h"
#include "terror.h"

/* see if multiple writers do create a consistent set of records. */

#define N_WRITER 3
#define N_RECORD 10000

static long vrandom() {
#define LOWBITS ((~((unsigned long)0)) >> 1)
    static unsigned long hash = 0xdeadbeef;

    return (hash = hash * 0xbadbeef + 0xdeadbeef) & LOWBITS;
}

tmain() {
    UNUSED(argc);
    UNUSED(argv);
    ssize_t size[N_WRITER][N_RECORD];
    int count[N_WRITER];
    char record[N_WRITER][128], *s;
    Sfio_t *fw[N_WRITER];
    Sfio_t *fr;
    int i, r, done;

    /* create random record sizes */
    for (i = 0; i < N_WRITER; ++i) {
        for (r = 0; r < N_RECORD; ++r) size[i][r] = (ssize_t)(vrandom() % 64) + 2;
    }

    /* records for different processes */
    for (i = 0; i < N_WRITER; ++i) {
        for (r = 0; r < 128; ++r) record[i][r] = '0' + i;
    }

    /* create file */
    fr = sfopen(NULL, tstfile("sf", 0), "w+");

    /* create records */
    for (i = 0; i < N_WRITER; ++i) {
        fw[i] = sfopen(NULL, tstfile("sf", 0), "a");
        count[i] = 0;
    }

    for (done = 0; done < N_WRITER;) {
        i = (int)(vrandom() % N_WRITER);
        if (count[i] < N_RECORD) {
            r = size[i][count[i]];
            if (!(s = sfreserve(fw[i], r, SF_LOCKR)) || sfvalue(fw[i]) < r) {
                terror("sfreserve fails in process %d", i);
            }
            memcpy(s, record[i], r - 1);
            s[r - 1] = '\n';
            sfwrite(fw[i], s, r);

            if ((count[i] += 1) == N_RECORD) {
                done += 1;
                sfclose(fw[i]);
            }
        }
    }

    for (i = 0; i < N_WRITER; ++i) count[i] = 0;

    while ((s = sfgetr(fr, '\n', 0))) {
        if ((i = s[0] - '0') < 0 || i >= N_WRITER) terror("Wrong record type");

        for (r = sfvalue(fr) - 2; r > 0; --r) {
            if (s[r] != s[0]) terror("Bad record%d, count=%d", i, count[i]);
        }

        if (sfvalue(fr) != size[i][count[i]]) {
            terror("Record%d count=%d size=%d sfvalue=%d", i, count[i], size[i][count[i]],
                   sfvalue(fr));
        }

        count[i] += 1;
    }

    for (i = 0; i < N_WRITER; ++i) {
        if (count[i] != N_RECORD) terror("Bad count%d %d", i, count[i]);
    }

    texit(0);
}
