Chandra

 view release on metacpan or  search on metacpan

include/chandra/chandra.h  view on Meta::CPAN

        Stat_t st;

        if (name[0] == '.') {
            if (name[1] == '\0') continue;
            if (name[1] == '.' && name[2] == '\0') continue;
        }

        fullpath_sv = newSVpvf("%s/%s", dir, name);
        fullpv = SvPV(fullpath_sv, fulllen);

        if (PerlLIO_stat(fullpv, &st) == 0) {
            if (S_ISREG(st.st_mode)) {
                (void)hv_store(files_hv, fullpv, (I32)fulllen,
                    newSVnv((NV)st.st_mtime), 0);
            } else if (S_ISDIR(st.st_mode)) {
                _hotreload_scan_recursive(aTHX_ fullpv, files_hv);
            }
        }

        SvREFCNT_dec(fullpath_sv);
    }

include/chandra/chandra_log.h  view on Meta::CPAN


static void
chandra_log_maybe_rotate(pTHX_ chandra_log_ctx *ctx, const char *path)
{
    Stat_t st;
    int keep, i;
    char from[4096], to[4096];

    if (ctx->rotate_max_size <= 0)
        return;
    if (PerlLIO_stat(path, &st) != 0)
        return;
    if (st.st_size < ctx->rotate_max_size)
        return;

    keep = ctx->rotate_keep;
    if (keep > CHANDRA_LOG_MAX_KEEP)
        keep = CHANDRA_LOG_MAX_KEEP;

    /* Delete oldest */
    snprintf(to, sizeof(to), "%s.%d", path, keep);

include/chandra/chandra_socket_hub.h  view on Meta::CPAN

    if (listener_svp && SvOK(*listener_svp)) {
        if (select_svp && SvOK(*select_svp))
            _sock_select_remove(aTHX_ *select_svp, *listener_svp);
        _sock_call_void(aTHX_ *listener_svp, "close");
        (void)hv_stores(hv, "_listener", newSV(0));
    }

    if (token_path_svp && SvOK(*token_path_svp)) {
        const char *tp = SvPV_nolen(*token_path_svp);
        Stat_t st;
        if (PerlLIO_stat(tp, &st) == 0)
            (void)PerlLIO_unlink(tp);
    }

    if (sock_path_svp && SvOK(*sock_path_svp)) {
        const char *sp = SvPV_nolen(*sock_path_svp);
        Stat_t st;
        if (PerlLIO_stat(sp, &st) == 0)
            (void)PerlLIO_unlink(sp);
    }

    /* Clean up TCP discovery file (Windows auto-upgrade) */
    {
        SV **disc_svp = hv_fetchs(hv, "_discovery_path", 0);
        if (disc_svp && SvOK(*disc_svp)) {
            const char *dp = SvPV_nolen(*disc_svp);
            Stat_t st;
            if (PerlLIO_stat(dp, &st) == 0)
                (void)PerlLIO_unlink(dp);
        }
    }
}

#endif /* CHANDRA_SOCKET_HUB_H */

include/chandra/chandra_store.h  view on Meta::CPAN

    size_t len;

#ifdef _WIN32
    /* Use Win32 API to avoid Perl's stat/mkdir macro redefinitions */
    DWORD attr = GetFileAttributesA(path);
    if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
        return 0;
#else
    {
        struct stat st;
        if (stat(path, &st) == 0) return 0;
    }
#endif

    strncpy(tmp, path, sizeof(tmp) - 1);
    tmp[sizeof(tmp) - 1] = '\0';
    len = strlen(tmp);
    if (len > 0 && tmp[len - 1] == '/') tmp[len - 1] = '\0';
#ifdef _WIN32
    /* Also handle backslash separators */
    if (len > 0 && tmp[len - 1] == '\\') tmp[len - 1] = '\0';

include/chandra/chandra_store.h  view on Meta::CPAN

#ifdef _WIN32
            {
                DWORD a = GetFileAttributesA(tmp);
                if (a == INVALID_FILE_ATTRIBUTES || !(a & FILE_ATTRIBUTE_DIRECTORY))
                    if (!CreateDirectoryA(tmp, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
                        return -1;
            }
#else
            {
                struct stat st;
                if (stat(tmp, &st) != 0)
                    if (mkdir(tmp, mode) != 0 && errno != EEXIST) return -1;
            }
#endif
            *p =
#ifdef _WIN32
                '\\';
#else
                '/';
#endif
        }

lib/Chandra/HotReload.pm  view on Meta::CPAN

	# Or integrated with App:
	$app->watch('lib/', sub {
	    my ($changed) = @_;
	    $app->set_content(rebuild());
	    $app->refresh;
	});
	$app->run;   # automatically polls during event loop

=head1 DESCRIPTION

Chandra::HotReload provides file-system watching via C<stat()> polling.
Register paths (files or directories) to watch along with callbacks
that are invoked whenever a change is detected.

When integrated with L<Chandra::App> via C<< $app->watch() >>, the
event loop automatically switches to non-blocking mode and polls for
file changes between iterations.

=head1 METHODS

=head2 new(%args)

xs/hotreload.xs  view on Meta::CPAN

    path = SvPV_nolen(path_sv);

    /* Validate callback */
    if (!SvOK(callback) || SvROK(callback) == 0 || SvTYPE(SvRV(callback)) != SVt_PVCV) {
        croak("watch() requires a callback");
    }

    /* Check path exists */
    {
        Stat_t st;
        if (PerlLIO_stat(path, &st) != 0) {
            croak("watch() path does not exist: %s", path);
        }
    }

    /* Scan files via Perl helper */
    {
        dSP;
        int count;
        ENTER; SAVETMPS;
        PUSHMARK(SP);

xs/hotreload.xs  view on Meta::CPAN

    SV *self
    SV *path_sv
CODE:
{
    const char *path = SvPV_nolen(path_sv);
    HV *files_hv = newHV();
    Stat_t st;

    PERL_UNUSED_VAR(self);

    if (PerlLIO_stat(path, &st) == 0) {
        if (S_ISREG(st.st_mode)) {
            /* Single file */
            STRLEN plen = SvCUR(path_sv);
            (void)hv_store(files_hv, path, (I32)plen, newSVnv((NV)st.st_mtime), 0);
        } else if (S_ISDIR(st.st_mode)) {
            /* Recursive C directory walk — no File::Find / eval_pv */
            _hotreload_scan_recursive(aTHX_ path, files_hv);
        }
    }



( run in 0.864 second using v1.01-cache-2.11-cpan-39bf76dae61 )