/* Entry point for serialization. Dumps generic SVs and delegates * to more specialized functions for RVs, etc. */ void ddl_dump_sv(pTHX_ ddl_encoder_t *enc, SV *src) { SvGETMAGIC(src); /* dump strings */ if (SvPOKp(src)) { STRLEN len; char *str = SvPV(src, len); BUF_SIZE_ASSERT(enc, 2 + len); ddl_dump_pv(aTHX_ enc, str, len, SvUTF8(src)); } /* dump floats */ else if (SvNOKp(src)) { BUF_SIZE_ASSERT(enc, NV_DIG + 32); Gconvert(SvNVX(src), NV_DIG, 0, enc->pos); enc->pos += strlen(enc->pos); } /* dump ints */ else if (SvIOKp(src)) { /* we assume we can always read an IV as a UV and vice versa * we assume two's complement * we assume no aliasing issues in the union */ if (SvIsUV(src) ? SvUVX(src) <= 59000 : SvIVX(src) <= 59000 && SvIVX(src) >= -59000) { /* optimise the "small number case" * code will likely be branchless and use only a single multiplication * works for numbers up to 59074 */ I32 i = SvIVX(src); U32 u; char digit, nz = 0; BUF_SIZE_ASSERT(enc, 6); *enc->pos = '-'; enc->pos += i < 0 ? 1 : 0; u = i < 0 ? -i : i; /* convert to 4.28 fixed-point representation */ u *= ((0xfffffff + 10000) / 10000); /* 10**5, 5 fractional digits */ /* now output digit by digit, each time masking out the integer part * and multiplying by 5 while moving the decimal point one to the right, * resulting in a net multiplication by 10. * we always write the digit to memory but conditionally increment * the pointer, to enable the use of conditional move instructions. */ digit = u >> 28; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0xfffffffUL) * 5; digit = u >> 27; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0x7ffffffUL) * 5; digit = u >> 26; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0x3ffffffUL) * 5; digit = u >> 25; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0x1ffffffUL) * 5; digit = u >> 24; *enc->pos = digit + '0'; enc->pos += 1; /* correctly generate '0' */ } else {
int ithread_mg_get(pTHX_ SV *sv, MAGIC *mg) { ithread *thread = (ithread *) mg->mg_ptr; SvIVX(sv) = PTR2IV(thread); SvIOK_on(sv); return 0; }
static void modify_event_perl(plcb_IOPROCS *async, plcb_EVENT *cevent, short flags) { SV **tmpsv; tmpsv = av_fetch(cevent->pl_event, PLCB_EVIDX_FD, 1); if (SvIOK(*tmpsv)) { SvIVX(*tmpsv) = cevent->fd; } else { sv_setiv(*tmpsv, cevent->fd); } SvIVX(async->flags_sv) = flags; /* Figure out the proper masks */ SvIVX(async->sched_r_sv) = flags & LCB_READ_EVENT && (cevent->flags & LCB_READ_EVENT) == 0; SvIVX(async->sched_w_sv) = flags & LCB_WRITE_EVENT && (cevent->flags & LCB_WRITE_EVENT) == 0; SvIVX(async->stop_r_sv) = (flags & LCB_READ_EVENT) == 0 && cevent->flags & LCB_READ_EVENT; SvIVX(async->stop_w_sv) = (flags & LCB_WRITE_EVENT) == 0 && cevent->flags & LCB_WRITE_EVENT; cb_args_noret(async->cv_evmod, 0, 7, async->userdata, cevent->rv_event, async->flags_sv, async->sched_r_sv, async->sched_w_sv, async->stop_r_sv, async->stop_w_sv); cevent->flags = flags; tmpsv = av_fetch(cevent->pl_event, PLCB_EVIDX_WATCHFLAGS, 1); SvIVX(*tmpsv) = cevent->flags; }
static void modify_timer_perl(plcb_IOPROCS *async, plcb_EVENT *cevent, uint32_t usecs, int action) { SvNVX(async->usec_sv) = (double) usecs / 1000000; SvIVX(async->action_sv) = action; cb_args_noret(async->cv_timermod, 0, 4, async->userdata, cevent->rv_event, async->action_sv, async->usec_sv); }
UV Perl_sv_uv(pTHX_ SV *sv) { PERL_ARGS_ASSERT_SV_UV; if (SvIOK(sv)) { if (SvIsUV(sv)) return SvUVX(sv); return (UV)SvIVX(sv); } return sv_2uv(sv); }
IV Perl_sv_iv(pTHX_ SV *sv) { PERL_ARGS_ASSERT_SV_IV; if (SvIOK(sv)) { if (SvIsUV(sv)) return (IV)SvUVX(sv); return SvIVX(sv); } return sv_2iv(sv); }
static JSBool perlarray_enumerate( JSContext *cx, JSObject *obj, JSIterateOp enum_op, jsval *statep, jsid *idp ) { dTHX; SV *ref = (SV *)JS_GetPrivate(cx, obj); AV *av = (AV *)SvRV(ref); PJS_ARRAY_CHECK if(enum_op == JSENUMERATE_INIT) { SV *cc = newSViv(0); *statep = PRIVATE_TO_JSVAL(cc); if(idp) { I32 alen = av_len(av); *idp = INT_TO_JSVAL(alen + 1); } return JS_TRUE; } if(enum_op == JSENUMERATE_NEXT) { SV *cc = (SV *)JSVAL_TO_PRIVATE(*statep); I32 alen = av_len(av); I32 curr; if(!SvIOK(cc)) { JS_ReportError(cx, "Wrong Array iterator"); return JS_FALSE; } curr = (I32)SvIVX(cc); if(curr > alen) { // At end *statep = JSVAL_NULL; sv_free(cc); } else { jsval key = INT_TO_JSVAL(curr); SvIV_set(cc, (IV)(curr+1)); return JS_ValueToId(cx, key, idp); } } return JS_TRUE; }
* resulting in a net multiplication by 10. * we always write the digit to memory but conditionally increment * the pointer, to enable the use of conditional move instructions. */ digit = u >> 28; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0xfffffffUL) * 5; digit = u >> 27; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0x7ffffffUL) * 5; digit = u >> 26; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0x3ffffffUL) * 5; digit = u >> 25; *enc->pos = digit + '0'; enc->pos += (nz = nz || digit); u = (u & 0x1ffffffUL) * 5; digit = u >> 24; *enc->pos = digit + '0'; enc->pos += 1; /* correctly generate '0' */ } else { /* large integer, use the (rather slow) snprintf way. */ BUF_SIZE_ASSERT(enc, IVUV_MAXCHARS); enc->pos += SvIsUV(src) ? snprintf(enc->pos, IVUV_MAXCHARS, "%"UVuf, (UV)SvUVX(src)) : snprintf(enc->pos, IVUV_MAXCHARS, "%"IVdf, (IV)SvIVX(src)); } } /* end is an integer */ /* undef */ else if (!SvOK(src)) { ddl_buf_cat_str_s(enc, "undef"); } /* dump references */ else if (SvROK(src)) ddl_dump_rv(aTHX_ enc, SvRV(src)); else { croak("Attempting to dump unsupported or invalid SV"); } }
int do_aspawn(SV* really, SV **mark, SV **sp) { char **a, *tmps; struct inheritance inherit; pid_t pid; int status, fd, nFd, fdMap[3]; SV *sv, **p_sv; STRLEN n_a; status = FAIL; if (sp > mark) { Newx(PL_Argv, sp - mark + 1, char*); a = PL_Argv; while (++mark <= sp) { if (*mark) *a++ = SvPVx(*mark, n_a); else *a++ = ""; } inherit.flags = SPAWN_SETGROUP; inherit.pgroup = SPAWN_NEWPGROUP; fdMap[STDIN_FILENO] = Perl_stdin_fd; fdMap[STDOUT_FILENO] = Perl_stdout_fd; fdMap[STDERR_FILENO] = STDERR_FILENO; nFd = 3; *a = NULL; /*-----------------------------------------------------*/ /* Will execvp() use PATH? */ /*-----------------------------------------------------*/ if (*PL_Argv[0] != '/') TAINT_ENV(); if (really && *(tmps = SvPV(really, n_a))) pid = spawnp(tmps, nFd, fdMap, &inherit, (const char **) PL_Argv, (const char **) environ); else pid = spawnp(PL_Argv[0], nFd, fdMap, &inherit, (const char **) PL_Argv, (const char **) environ); if (pid < 0) { status = FAIL; if (ckWARN(WARN_EXEC)) warner(WARN_EXEC,"Can't exec \"%s\": %s", PL_Argv[0], Strerror(errno)); } else { /*------------------------------------------------*/ /* If the file descriptors have been remapped then*/ /* we've been called following a my_popen request */ /* therefore we don't want to wait for spawnned */ /* program to complete. We need to set the fdpid */ /* value to the value of the spawnned process' pid*/ /*------------------------------------------------*/ fd = 0; if (Perl_stdin_fd != STDIN_FILENO) fd = Perl_stdin_fd; else if (Perl_stdout_fd != STDOUT_FILENO) fd = Perl_stdout_fd; if (fd != 0) { /*---------------------------------------------*/ /* Get the fd of the other end of the pipe, */ /* use this to reference the fdpid which will */ /* be used by my_pclose */ /*---------------------------------------------*/ close(fd); MUTEX_LOCK(&PL_fdpid_mutex); p_sv = av_fetch(PL_fdpid,fd,TRUE); fd = (int) SvIVX(*p_sv); SvREFCNT_dec(*p_sv); *p_sv = &PL_sv_undef; sv = *av_fetch(PL_fdpid,fd,TRUE); MUTEX_UNLOCK(&PL_fdpid_mutex); (void) SvUPGRADE(sv, SVt_IV); SvIVX(sv) = pid; status = 0; } else wait4pid(pid, &status, 0); } do_execfree(); }
SV * parse_in_chunks(char * filepath, size_t filesize) { char *buf; size_t bytes_read = 0; int max_buf = 1000; char *err_msg; int block = BLOCK_HEADER; int cur_event_type = 0; int event_type = 0; char event_block = 0; char *brnl, *breq; AV * data; AV * datawrapper; AV * events; char *line; char * nl = "\n"; char * eq = "="; int rewind_pos = 0; size_t cur_fpos = 0; SV * pbuf; SV * pmax_buf; AV * HANDLERS = get_av("Opsview::Utils::NDOLogsImporter::HANDLERS", 0); AV * INPUT_DATA_TYPE = get_av("Opsview::Utils::NDOLogsImporter::INPUT_DATA_TYPE", 0); int init_last_pos; int init_block; if ( first_read ) { if ( ! ( fh = PerlIO_open( filepath, "rb" ) ) ) { croak("Could not open file: %s\n", strerror(errno)); } bytes_left = filesize; init_last_pos = prev_pos = first_read = 0; init_block = block = BLOCK_HEADER; } else { init_block = block = BLOCK_EVENTS; init_last_pos = prev_pos; } read_begin: brnl = NULL; breq = NULL; pbuf = get_sv("Opsview::Utils::NDOLogsImporter::PARSE_BUF", 0); pmax_buf = get_sv("Opsview::Utils::NDOLogsImporter::MAX_BUF_SIZE", 0); buf = SvPVX(pbuf); max_buf = SvIVX(pmax_buf); if ( max_buf < 1024 * 1024 && ! automated_tests ) { max_buf = 1024*1024; SvIV_set( pmax_buf, max_buf ); SvGROW( pbuf, max_buf + 1); SvCUR_set( pbuf, max_buf); } if ( bytes_left > 0 ) { bytes_read = PerlIO_read(fh, buf + prev_pos, max_buf-prev_pos); cur_fpos = PerlIO_tell(fh); if ( bytes_read < 0 ) { err_msg = strerror(errno); PerlIO_close( fh ); croak("Could not read file: %s\n", err_msg); } bytes_left -= bytes_read; events = (AV *)sv_2mortal((SV *)newAV()); rewind_pos = last_999(buf+prev_pos, bytes_read); prev_pos = bytes_read + prev_pos - rewind_pos; buf[prev_pos] = '\0'; // avg ratio events:file_size = 0.21% if ( prev_pos > 1000 ) { av_extend( events, (int)(prev_pos * 0.0021) ); } for ( line = strtok_r(buf, nl, &brnl); line != NULL; line = strtok_r(NULL, nl, &brnl) ) { switch(block) { case BLOCK_HEADER: { if ( strEQ(line, "STARTDATADUMP") ) { block = BLOCK_EVENTS; } } break; case BLOCK_EVENTS: { if ( strEQ(line, "1000") ) { /* NDO_API_ENDDATADUMP */ block = BLOCK_FOOTER; continue; } cur_event_type = atoi(line); /* ignore events we are not handling */ if ( ! av_exists(HANDLERS, cur_event_type) ) { block = BLOCK_IGNORE_EVENT; continue; } event_block = BLOCK_EVENT_STARTED; if ( cur_event_type != event_type ) { datawrapper = (AV *)sv_2mortal((SV *)newAV()); data = (AV *)sv_2mortal((SV *)newAV()); av_push( events, newSViv( cur_event_type ) ); av_push( datawrapper, newRV( (SV *)data ) ); av_push( events, newRV( (SV *)datawrapper ) ); event_type = cur_event_type; } else { data = (AV *)sv_2mortal((SV *)newAV()); av_push( datawrapper, newRV( (SV *)data ) ); } block = BLOCK_EVENT; } break; case BLOCK_EVENT: { if ( strEQ(line, "999") ) { /* NDO_API_ENDDATA */ block = BLOCK_EVENTS; event_block = BLOCK_EVENT_ENDED; } else { char *k; char *v; int key; int key_type = 0; int v_len = 0; k = strtok_r(line, eq, &breq); v = strtok_r(NULL, "\0", &breq); key = atoi(k); /* invalid key, skip parsing */ if ( key == 0 ) { goto remove_invalid; } SV ** const k_type = av_fetch(INPUT_DATA_TYPE, key, 0 ); if ( k_type ) { key_type = SvIVx( *k_type ); } if ( v ) { if ( key_type & 1 ) { v_len = ndo_unescape_buffer( v ); } else { v_len = strlen(v); } } if ( key_type & 2 ) { AV * datanstptr; SV ** const datanst = av_fetch(data, key, 0 ); if ( datanst ) { datanstptr = (AV *)SvRV( *datanst ); } else { datanstptr = (AV *)sv_2mortal((SV *)newAV()); av_store( data, key, newRV( (SV *)datanstptr ) ); } if ( v ) { av_push( datanstptr, newSVpvn(v, v_len) ); } else { av_push( datanstptr, newSVpvn("", 0) ); } } else { if ( v ) { av_store( data, key, newSVpvn(v, v_len) ); } else { av_store( data, key, newSVpvn("", 0) ); } } } } break; case BLOCK_FOOTER: { if ( strEQ(line, "GOODBYE") ) { block = BLOCK_HEADER; } } break; case BLOCK_IGNORE_EVENT: { if ( strEQ(line, "999") ) { /* NDO_API_ENDDATA */ block = BLOCK_EVENTS; // go back to EVENTS continue; } } break; } }; /* there were some events */ if ( event_block != BLOCK_HEADER ) { if ( event_block != BLOCK_EVENT_ENDED ) { remove_invalid: av_pop( datawrapper ); } /* remove whole block if the last block has no events */ if ( av_len( datawrapper ) == -1 ) { av_pop( events ); av_pop( events ); } } if ( av_len(events) > 0 ) { if ( rewind_pos > 0 && cur_fpos < filesize ) { memmove(buf, buf+prev_pos+1, rewind_pos-1); } prev_pos = rewind_pos - 1; return newRV_inc((SV *) events); } else { if ( cur_fpos < filesize && event_block != BLOCK_HEADER && event_block != BLOCK_EVENT_ENDED ) { int new_max_buf = max_buf * 2; SvIV_set( pmax_buf, new_max_buf ); SvGROW( pbuf, new_max_buf + 1); SvCUR_set( pbuf, new_max_buf); //start again as previous buffer would be tokenized already prev_pos = 0; block = init_block; event_type = 0; PerlIO_close( fh ); if ( ! ( fh = PerlIO_open( filepath, "rb" ) ) ) { croak("Could not re-open file: %s\n", strerror(errno)); } PerlIO_seek(fh, cur_fpos-bytes_read-init_last_pos, SEEK_SET); bytes_left += bytes_read + init_last_pos; goto read_begin; } } } parser_reset_iterator(); return &PL_sv_undef; }