<commit_before>/**
 * \file
 * \brief ramfs service
 */

/*
 * Copyright (c) 2010, ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 */

#include <string.h>
#include <barrelfish/barrelfish.h>
#include <barrelfish/nameservice_client.h>
#include <barrelfish/bulk_transfer.h>
#include <barrelfish/vregion.h>
#include <if/trivfs_defs.h>
#include <if/monitor_defs.h>

#include "ramfs.h"

#define SERVICE_NAME    "ramfs"

#define FHTAB_SIZE_BITS 8
#define FHTAB_SIZE_MASK ((1U << FHTAB_SIZE_BITS) - 1)
#define FHTAB_LEN       (1U << FHTAB_SIZE_BITS)
#define FH_BITS         (sizeof(trivfs_fh_t) * NBBY)
#define FHGEN_BITS      (FH_BITS - FHTAB_SIZE_BITS)

#define NULL_FH         ((trivfs_fh_t)-1u)

struct msgq_elem {
    enum trivfs_msg_enum msgnum;
    union trivfs_rx_arg_union a;
    struct dirent *dirent;
    struct msgq_elem *next;
};

struct client_state {
    struct dirent *root;
    struct dirent *fhtab[FHTAB_LEN];
    unsigned fhindex, fhgen;
    struct msgq_elem *qstart, *qend; ///< queue of pending replies
    struct bulk_transfer_slave bulk;
    struct vregion *bulk_vregion;
};

/* ------------------------------------------------------------------------- */

static void client_state_init(struct client_state *st, struct dirent *root)
{
    st->root = root;
    memset(st->fhtab, 0, sizeof(st->fhtab));
    st->fhindex = 0;
    st->fhgen = 0;
    st->qstart = st->qend = NULL;
    st->bulk_vregion = NULL;
}

static trivfs_fh_t fh_set(struct client_state *st, struct dirent *d)
{
    // use the next index slot
    st->fhtab[st->fhindex] = d;
    ramfs_incref(d);

    // construct fh: generation and index
    trivfs_fh_t fh = ((trivfs_fh_t)st->fhgen << FHTAB_SIZE_BITS) | st->fhindex;

    // update index (and generation if needed)
    if (++st->fhindex == FHTAB_LEN) {
        st->fhindex = 0;
        st->fhgen++;
    }

    return fh;
}

static struct dirent *fh_get(struct client_state *st, trivfs_fh_t fh)
{
    // unpack fh
    unsigned gen = fh >> FHTAB_SIZE_BITS;
    unsigned idx = fh & FHTAB_SIZE_MASK;

    // check if it's still valid
    struct dirent *e = NULL;
    if ((gen == st->fhgen && idx < st->fhindex)
        || (gen == st->fhgen - 1 && idx >= st->fhindex)) {
        e = st->fhtab[idx];
    }

    if (e == NULL) {
        return NULL; // invalid or stale
    }

    if (ramfs_islive(e)) {
        return e; // valid
    }

    // has been deleted
    st->fhtab[idx] = NULL;
    ramfs_decref(e);
    return NULL;
}

/* ------------------------------------------------------------------------- */

static errval_t ramfs_bulk_init(struct trivfs_binding *b, struct capref shared_frame,
                                errval_t *reterr)
{
    struct client_state *st = b->st;
    errval_t err;

    *reterr = SYS_ERR_OK;

    if (st->bulk_vregion != NULL) {
        *reterr = FS_ERR_BULK_ALREADY_INIT;
        cap_destroy(shared_frame);
        return SYS_ERR_OK;
    }

    // Determine size of frame
    struct frame_identity frameid;
    err = invoke_frame_identify(shared_frame, &frameid);
    if (err_is_fail(err)) {
        *reterr = err_push(err, LIB_ERR_FRAME_IDENTIFY);
        cap_destroy(shared_frame);
        return SYS_ERR_OK;
    }

    size_t bulk_size = frameid.bytes;

    // Map the frame in local memory
    void *bulk_pool;
    err = vspace_map_one_frame_attr(&bulk_pool, bulk_size, shared_frame,
                                    VREGION_FLAGS_READ_WRITE_MPB, NULL,
                                    &st->bulk_vregion);
    if (err_is_fail(err)) {
        cap_destroy(shared_frame);
        *reterr = err_push(err, LIB_ERR_VSPACE_MAP);
        return SYS_ERR_OK;
    }
    assert(bulk_pool != NULL);
    assert(st->bulk_vregion != NULL);

    // Init the bulk transfer library
    err = bulk_slave_init(bulk_pool, bulk_size, &st->bulk);
    assert(err_is_ok(err));

    return SYS_ERR_OK;
}

static errval_t getroot(struct trivfs_binding *b, trivfs_fh_t *rootfh)
{
    struct client_state *st = b->st;
    *rootfh = fh_set(st, st->root);

    return SYS_ERR_OK;
}

static errval_t readdir(struct trivfs_binding *b, trivfs_fh_t dir, uint32_t idx,
                        errval_t *reterr, char name[2048], bool *isdir,
                        trivfs_fsize_t *size)
{
    errval_t err;
    *reterr = SYS_ERR_OK;
    struct client_state *st = b->st;
    name[0] = 0;
    *isdir = false;
    *size = 0;

    struct dirent *d = fh_get(st, dir);
    if (d == NULL) {
        *reterr = FS_ERR_INVALID_FH;
        return SYS_ERR_OK;
    }

    struct dirent *e = NULL;
    err = ramfs_readdir(d, idx, &e);
    if (err_is_fail(err)) {
        *reterr = err;
        return SYS_ERR_OK;
    } else if (e == NULL) {
        *reterr = FS_ERR_INDEX_BOUNDS;
        return SYS_ERR_OK;
    }

    ramfs_incref(e);
    strncpy(name, ramfs_get_name(e), sizeof(name));
    *isdir = ramfs_isdir(e);
    *size = ramfs_get_size(e);
    return SYS_ERR_OK;
}

static errval_t lookup(struct trivfs_binding *b, trivfs_fh_t dir, char *name,
                       errval_t *reterr, trivfs_fh_t *retfh, bool *isdir)
{
    errval_t err;
    *reterr = SYS_ERR_OK;
    struct client_state *st = b->st;<commit_msg>Fix compiler warnings in ramfsd<commit_after>/**
 * \file
 * \brief ramfs service
 */

/*
 * Copyright (c) 2010, ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 */

#include <string.h>
#include <barrelfish/barrelfish.h>
#include <barrelfish/nameservice_client.h>
#include <barrelfish/bulk_transfer.h>
#include <barrelfish/vregion.h>
#include <if/trivfs_defs.h>
#include <if/monitor_defs.h>

#include "ramfs.h"

#define SERVICE_NAME    "ramfs"

#define FHTAB_SIZE_BITS 8
#define FHTAB_SIZE_MASK ((1U << FHTAB_SIZE_BITS) - 1)
#define FHTAB_LEN       (1U << FHTAB_SIZE_BITS)
#define FH_BITS         (sizeof(trivfs_fh_t) * NBBY)
#define FHGEN_BITS      (FH_BITS - FHTAB_SIZE_BITS)

#define NULL_FH         ((trivfs_fh_t)-1u)

struct msgq_elem {
    enum trivfs_msg_enum msgnum;
    union trivfs_rx_arg_union a;
    struct dirent *dirent;
    struct msgq_elem *next;
};

struct client_state {
    struct dirent *root;
    struct dirent *fhtab[FHTAB_LEN];
    unsigned fhindex, fhgen;
    struct msgq_elem *qstart, *qend; ///< queue of pending replies
    struct bulk_transfer_slave bulk;
    struct vregion *bulk_vregion;
};

/* ------------------------------------------------------------------------- */

static void client_state_init(struct client_state *st, struct dirent *root)
{
    st->root = root;
    memset(st->fhtab, 0, sizeof(st->fhtab));
    st->fhindex = 0;
    st->fhgen = 0;
    st->qstart = st->qend = NULL;
    st->bulk_vregion = NULL;
}

static trivfs_fh_t fh_set(struct client_state *st, struct dirent *d)
{
    // use the next index slot
    st->fhtab[st->fhindex] = d;
    ramfs_incref(d);

    // construct fh: generation and index
    trivfs_fh_t fh = ((trivfs_fh_t)st->fhgen << FHTAB_SIZE_BITS) | st->fhindex;

    // update index (and generation if needed)
    if (++st->fhindex == FHTAB_LEN) {
        st->fhindex = 0;
        st->fhgen++;
    }

    return fh;
}

static struct dirent *fh_get(struct client_state *st, trivfs_fh_t fh)
{
    // unpack fh
    unsigned gen = fh >> FHTAB_SIZE_BITS;
    unsigned idx = fh & FHTAB_SIZE_MASK;

    // check if it's still valid
    struct dirent *e = NULL;
    if ((gen == st->fhgen && idx < st->fhindex)
        || (gen == st->fhgen - 1 && idx >= st->fhindex)) {
        e = st->fhtab[idx];
    }

    if (e == NULL) {
        return NULL; // invalid or stale
    }

    if (ramfs_islive(e)) {
        return e; // valid
    }

    // has been deleted
    st->fhtab[idx] = NULL;
    ramfs_decref(e);
    return NULL;
}

/* ------------------------------------------------------------------------- */

static errval_t ramfs_bulk_init(struct trivfs_binding *b, struct capref shared_frame,
                                errval_t *reterr)
{
    struct client_state *st = b->st;
    errval_t err;

    *reterr = SYS_ERR_OK;

    if (st->bulk_vregion != NULL) {
        *reterr = FS_ERR_BULK_ALREADY_INIT;
        cap_destroy(shared_frame);
        return SYS_ERR_OK;
    }

    // Determine size of frame
    struct frame_identity frameid;
    err = invoke_frame_identify(shared_frame, &frameid);
    if (err_is_fail(err)) {
        *reterr = err_push(err, LIB_ERR_FRAME_IDENTIFY);
        cap_destroy(shared_frame);
        return SYS_ERR_OK;
    }

    size_t bulk_size = frameid.bytes;

    // Map the frame in local memory
    void *bulk_pool;
    err = vspace_map_one_frame_attr(&bulk_pool, bulk_size, shared_frame,
                                    VREGION_FLAGS_READ_WRITE_MPB, NULL,
                                    &st->bulk_vregion);
    if (err_is_fail(err)) {
        cap_destroy(shared_frame);
        *reterr = err_push(err, LIB_ERR_VSPACE_MAP);
        return SYS_ERR_OK;
    }
    assert(bulk_pool != NULL);
    assert(st->bulk_vregion != NULL);

    // Init the bulk transfer library
    err = bulk_slave_init(bulk_pool, bulk_size, &st->bulk);
    assert(err_is_ok(err));

    return SYS_ERR_OK;
}

static errval_t getroot(struct trivfs_binding *b, trivfs_fh_t *rootfh)
{
    struct client_state *st = b->st;
    *rootfh = fh_set(st, st->root);

    return SYS_ERR_OK;
}

#define NAME_SIZE 2048
static errval_t readdir(struct trivfs_binding *b, trivfs_fh_t dir, uint32_t idx,
                        errval_t *reterr, char * name, bool *isdir,
                        trivfs_fsize_t *size)
{
    errval_t err;
    *reterr = SYS_ERR_OK;
    struct client_state *st = b->st;
    name[0] = 0;
    *isdir = false;
    *size = 0;

    struct dirent *d = fh_get(st, dir);
    if (d == NULL) {
        *reterr = FS_ERR_INVALID_FH;
        return SYS_ERR_OK;
    }

    struct dirent *e = NULL;
    err = ramfs_readdir(d, idx, &e);
    if (err_is_fail(err)) {
        *reterr = err;
        return SYS_ERR_OK;
    } else if (e == NULL) {
        *reterr = FS_ERR_INDEX_BOUNDS;
        return SYS_ERR_OK;
    }

    ramfs_incref(e);
    strncpy(name, ramfs_get_name(e),NAME_SIZE);
    *isdir = ramfs_isdir(e);
    *size = ramfs_get_size(e);
    return SYS_ERR_OK;
}

static errval_t lookup(struct trivfs_binding *b, trivfs_fh_t dir, char *name,
                       errval_t *reterr, trivfs_fh_t *retfh, bool *isdir)
{
    errval_t err;
    *reterr = SYS_ERR_OK;
    struct client_state *st = b->st;
{'fraction_non_alphanumeric': 0.13962580284836637, 'fraction_numerical': 0.005212696639672345, 'mean_word_length': 2.3828715365239295, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3266473', 'n_tokens_mistral': 4147, 'n_tokens_neox': 3947, 'n_words': 909}