Net-LibNFS

 view release on metacpan or  search on metacpan

LibNFS.xs  view on Meta::CPAN

#define MAX_BUFFER_SIZE_ARRAY_SIZE 2
#define READDIR_BUFFER_SETTING "readdir_buffer"

static void _set_readdir_max_buffer_size(pTHX_ struct nfs_context* nfs, SV* value_sv) {

    uint32_t dircount, maxcount;

    if (SvROK(value_sv) && (SvTYPE(SvRV(value_sv)) == SVt_PVAV)) {
        AV* av = (AV*) SvRV(value_sv);
        uint32_t nums_count = 1 + av_len(av);
        if (nums_count != MAX_BUFFER_SIZE_ARRAY_SIZE) croak("“%s” must contain exactly %d numbers", READDIR_BUFFER_SETTING, MAX_BUFFER_SIZE_ARRAY_SIZE);

        uint32_t nums[MAX_BUFFER_SIZE_ARRAY_SIZE];

        for (unsigned n=0; n<nums_count; n++) {
            SV** svp = av_fetch(av, n, 0);
            assert(svp);

            UV value = exs_SvUV(*svp);
            _croak_if_uv_exceeds_u32(READDIR_BUFFER_SETTING, value);

            nums[n] = value;
        }

        dircount = nums[0];
        maxcount = nums[1];
    } else if (SvROK(value_sv)) {
        croak("“%s” must be an array reference or scalar, not %" SVf, READDIR_BUFFER_SETTING, value_sv);
    } else {
        UV value = exs_SvUV(value_sv);
        _croak_if_uv_exceeds_u32(READDIR_BUFFER_SETTING, value);

        dircount = value;
        maxcount = value;
    }

    nfs_set_readdir_max_buffer_size(nfs, dircount, maxcount);
}
#endif

// ----------------------------------------------------------------------

MODULE = Net::LibNFS        PACKAGE = Net::LibNFS

PROTOTYPES: DISABLE

BOOT:
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "_POLLIN", newSVuv(POLLIN));
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "_POLLOUT", newSVuv(POLLOUT));
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "NFS4_F_SETLK", newSVuv(NFS4_F_SETLK));
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "NFS4_F_SETLKW", newSVuv(NFS4_F_SETLKW));
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "F_RDLCK", newSVuv(F_RDLCK));
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "F_WRLCK", newSVuv(F_WRLCK));
    newCONSTSUB(gv_stashpv(PERL_NS, 0), "F_UNLCK", newSVuv(F_UNLCK));

# ----------------------------------------------------------------------
# Static functions

void
find_local_servers ()
    PPCODE:
        struct nfs_server_list *servers = nfs_find_local_servers();

        if (!servers) {
            XSRETURN_EMPTY;
        }

        struct nfs_server_list *srvlist = servers;
        struct nfs_server_list *cur_srv = srvlist;

        unsigned srvcount = 0;

        while (cur_srv) {
            srvcount++;
            cur_srv = cur_srv->next;
        }

        cur_srv = srvlist;

        if (srvcount) {
            EXTEND(SP, srvcount);

            while (cur_srv) {
                mPUSHs( newSVpv(cur_srv->addr, 0) );
                cur_srv = cur_srv->next;
            }
        }

        free_nfs_srvr_list(srvlist);

void
mount_getexports (SV* server_sv, SV* timeout_sv=&PL_sv_undef)
    PPCODE:
        const char* server = exs_SvPVbyte_nolen(server_sv);

        struct exportnode* nodes;

        if (SvOK(timeout_sv)) {
            int timeout = SvIV(timeout_sv); // TODO
            nodes = mount_getexports_timeout(server, timeout);
        }
        else {
            nodes = mount_getexports(server);
        }

        if (!nodes) {
            XSRETURN_EMPTY;
        }

        unsigned exports_count = _count_exports(nodes);
        SV* export_hrs[exports_count];

        _parse_exports_to_hrs( aTHX_ nodes, export_hrs );

        mount_free_export_list(nodes);

# ----------------------------------------------------------------------

SV*
new (const char* classname)
    CODE:
        struct nfs_context *nfs = nfs_init_context();
        if (NULL == nfs) {
            croak("Failed to init libnfs context");
        }

        RETVAL = exs_new_structref(nlnfs_s, classname);
        nlnfs_s* perl_nfs = exs_structref_ptr(RETVAL);

        *perl_nfs = (nlnfs_s) {
            .nfs = nfs,
            .pid = getpid(),
        };

    OUTPUT:
        RETVAL

void
DESTROY (SV* self_sv)
    CODE:
        nlnfs_s* perl_nfs = exs_structref_ptr(self_sv);

        if (perl_nfs->pid == getpid() && PL_dirty) {
            warn("%" SVf ": DESTROY at global destruction; memory leak likely!\n", self_sv);
        }

        assert(perl_nfs);
        assert(perl_nfs->nfs);

        nfs_destroy_context(perl_nfs->nfs);

SV*
set (SV* self_sv, ...)

LibNFS.xs  view on Meta::CPAN


        const char* server = exs_SvPVbyte_nolen(server_sv);

        const char* funcname = "mount_getexports";

        perl_cb_s* cb_sp = _create_callback_struct(aTHX_ funcname, cb, _parse_mount_getexports, NULL);

        int err = mount_getexports_async(rpc, server, _do_perl_rpc_callback, cb_sp);

        if (err) {
            const char* str = rpc_get_error(rpc);
            croak_sv( _create_rpc_errno(aTHX_ rpc, funcname, err, str) );
        }

int
_get_fd (SV* self_sv)
    ALIAS:
        _which_events = 1
    CODE:
        nlnfs_rpc_s* perl_rpc = exs_structref_ptr(self_sv);
        struct rpc_context *rpc = perl_rpc->rpc;

        RETVAL = ix ? rpc_which_events(rpc) : rpc_get_fd(rpc);
    OUTPUT:
        RETVAL

int
_service (SV* self_sv, int revents)
    CODE:
        nlnfs_rpc_s* perl_rpc = exs_structref_ptr(self_sv);
        struct rpc_context *rpc = perl_rpc->rpc;

        RETVAL = rpc_service(rpc, revents);

    OUTPUT:
        RETVAL

# ----------------------------------------------------------------------

MODULE = Net::LibNFS        PACKAGE = Net::LibNFS::Dirhandle

PROTOTYPES: DISABLE

void
DESTROY (SV* self_sv)
    CODE:
        nlnfs_dh_s* nfs_dh = exs_structref_ptr(self_sv);

        if (!nfs_dh->closed) {
            SV* nfs_sv = nfs_dh->perl_nfs;

            nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

            nfs_closedir( perl_nfs->nfs, nfs_dh->nfsdh );
        }

        SvREFCNT_dec(nfs_dh->perl_nfs);

void
read (SV* self_sv)
    PPCODE:
        _FORBID_VOID_CONTEXT;

        nlnfs_dh_s* nfs_dh = exs_structref_ptr(self_sv);

        SV* nfs_sv = nfs_dh->perl_nfs;

        nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

        unsigned retcount = 0;
        struct nfsdirent* dent = nfs_readdir( perl_nfs->nfs, nfs_dh->nfsdh );
        struct nfsdirent* cur_dent = dent;

        while (cur_dent) {
            retcount++;
            if (GIMME_V != G_ARRAY) break;

            cur_dent = cur_dent->next;
        }

        if (retcount) {
            EXTEND(SP, retcount);

            unsigned retcount_copy = retcount;

            while (1) {
                mPUSHs(_ptr_to_perl_dirent_obj(aTHX_ dent));

                retcount_copy--;
                if (!retcount_copy) break;

                dent = nfs_readdir( perl_nfs->nfs, nfs_dh->nfsdh );
            }
        }

        XSRETURN(retcount);

SV*
seek (SV* self_sv, SV* loc_sv)
    CODE:
        nlnfs_dh_s* nfs_dh = exs_structref_ptr(self_sv);

        SV* nfs_sv = nfs_dh->perl_nfs;

        nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

        long loc = SvIV(loc_sv);    // TODO

        nfs_seekdir( perl_nfs->nfs, nfs_dh->nfsdh, loc );

        RETVAL = SvREFCNT_inc(self_sv);

    OUTPUT:
        RETVAL

long
tell (SV* self_sv)
    CODE:
        nlnfs_dh_s* nfs_dh = exs_structref_ptr(self_sv);

        SV* nfs_sv = nfs_dh->perl_nfs;

        nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

        RETVAL = nfs_telldir( perl_nfs->nfs, nfs_dh->nfsdh );

        if (RETVAL < 0) {
            _croak_nfs_errno(aTHX_ perl_nfs->nfs, "telldir", RETVAL, NULL);
        }

    OUTPUT:
        RETVAL

SV*
rewind (SV* self_sv)
    ALIAS:
        close = 1
    CODE:
        nlnfs_dh_s* nfs_dh = exs_structref_ptr(self_sv);

        SV* nfs_sv = nfs_dh->perl_nfs;

        nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

        if (ix) {
            if (!nfs_dh->closed) {
                nfs_closedir( perl_nfs->nfs, nfs_dh->nfsdh );
                nfs_dh->closed = true;
            }
        }
        else {
            nfs_rewinddir( perl_nfs->nfs, nfs_dh->nfsdh );
        }

        RETVAL = SvREFCNT_inc(self_sv);
    OUTPUT:
        RETVAL

# ----------------------------------------------------------------------

MODULE = Net::LibNFS        PACKAGE = Net::LibNFS::Filehandle

PROTOTYPES: DISABLE

void
DESTROY (SV* self_sv)
    CODE:
        nlnfs_fh_s* nfs_fh = exs_structref_ptr(self_sv);

        SvREFCNT_dec(nfs_fh->perl_nfs);

void
close (SV* self_sv)
    PPCODE:
        nlnfs_fh_s* nfs_fh = exs_structref_ptr(self_sv);

        SV* nfs_sv = nfs_fh->perl_nfs;

        nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

        int err = nfs_close(perl_nfs->nfs, nfs_fh->nfsfh);

        if (err) {
            _croak_nfs_errno(aTHX_ perl_nfs->nfs, "close", err, NULL);
        }

        XSRETURN_EMPTY;

void
_async_close (SV* self_sv, SV* cb)
    ALIAS:
        _async_sync = 1
    CODE:
        nlnfs_fh_s* nfs_fh = exs_structref_ptr(self_sv);

        SV* nfs_sv = nfs_fh->perl_nfs;

        nlnfs_s* perl_nfs = exs_structref_ptr(nfs_sv);

        const char* funcname = ix ? "sync" : "close";

        perl_cb_s* cb_sp = _create_callback_struct(aTHX_ funcname, cb, _parse_fallible_empty_return, NULL);

        int err;

        if (ix) {
            err = nfs_fsync_async(perl_nfs->nfs, nfs_fh->nfsfh, _do_perl_callback, cb_sp);
        }
        else {
            err = nfs_close_async(perl_nfs->nfs, nfs_fh->nfsfh, _do_perl_callback, cb_sp);
        }

        if (err) {
            _croak_nfs_errno(aTHX_ perl_nfs->nfs, funcname, err, NULL);
        }

SV*
read (SV* self_sv, SV* count_sv)
    CODE:
        RETVAL = _read_or_pread(aTHX_ self_sv, NULL, count_sv, NULL);
    OUTPUT:
        RETVAL

void
_async_read (SV* self_sv, SV* count_sv, SV* cb)
    CODE:
        _read_or_pread(aTHX_ self_sv, NULL, count_sv, cb);

SV*
pread (SV* self_sv, SV* offset_sv, SV* count_sv)
    CODE:
        RETVAL = _read_or_pread(aTHX_ self_sv, offset_sv, count_sv, NULL);
    OUTPUT:
        RETVAL



( run in 1.054 second using v1.01-cache-2.11-cpan-5511b514fd6 )