Sort-External
view release on metacpan or search on metacpan
External.xs view on Meta::CPAN
if (digit < 0x80) break;
}
{
/* Recover the stringified scalar from disk. */
SV *item_sv = newSV(item_length + 1);
char flags;
SvCUR_set(item_sv, item_length);
SvPOK_on(item_sv);
check = PerlIO_read(fh, SvPVX(item_sv), item_length);
if (check < (int)item_length) {
croak("PerlIO error: read %d bytes, expected %"UVuf" bytes",
check, (UV)item_length);
}
self->pos += check;
*(SvEND(item_sv)) = '\0'; /* Null-terminate. */
/* Restore UTF8 and taint flags. */
check = PerlIO_read(fh, &flags, 1);
self->pos++;
if (check < 1) croak("PerlIO failed: %s", strerror(errno));
if (flags & SORTEX_UTF8_FLAG) SvUTF8_on(item_sv);
if (flags & SORTEX_TAINTED_FLAG) SvTAINTED_on(item_sv);
/* Add to the buffarray. */
av_push(buffarray_av, item_sv);
/* Track how much we've read so far. */
num_items++;
}
}
return num_items;
}
MODULE = Sort::External PACKAGE = Sort::External
PROTOTYPES: DISABLE
SV*
_new(class_name, working_dir, sortsub, cache_size, mem_threshold, tempfile_fh)
char *class_name;
SV *working_dir;
SV *sortsub;
IV cache_size;
IV mem_threshold;
SV *tempfile_fh;
CODE:
{
SortExternal *self = SortEx_new(working_dir, sortsub, cache_size,
mem_threshold, tempfile_fh);
RETVAL = newSV(0);
sv_setref_pv(RETVAL, class_name, (void*)self);
}
OUTPUT: RETVAL
void
DESTROY(self)
SortExternal *self;
PPCODE:
SortEx_destroy(self);
void
feed(self, ...)
SortExternal *self;
PPCODE:
{
AV *const item_cache = self->item_cache;
I32 start = av_len(item_cache) + 1;
I32 new_size = start + items - 1;
IV space = (OVERHEAD + sizeof(SV*)) * (items - 1);
I32 i;
int need_to_flush = 0;
/* Push arguments onto cache array. */
av_extend(self->item_cache, new_size);
for (i = 1; i < items; i++) {
SV *const element = ST(i);
SV *const copy = newSVsv(element);
av_push(item_cache, copy);
/* Calculate a rough estimate of the memory occupied by the arguments:
* sum the allocated string lengths, plus 15 bytes per scalar as
* overhead. Also, sv_len() has a side-effect of stringifying the SV.
*/
space += sv_len(copy);
}
self->mem_bytes += space;
if (self->cache_size > 0) {
/* Use the number of cache elements as a flush-trigger. */
if (av_len(self->item_cache) + 1 >= self->cache_size)
need_to_flush = 1;
}
else if (self->mem_bytes > self->mem_threshold) {
/* Use memory consumption as a flush-trigger. */
need_to_flush = 1;
}
if (need_to_flush) {
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( ST(0) );
call_method("_write_item_cache_to_tempfile", G_VOID|G_DISCARD);
PUTBACK;
FREETMPS;
LEAVE;
}
}
void
fetch(self)
SortExternal *self;
PPCODE:
{
if (self->fetch_tick > av_len(self->item_cache)) {
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( ST(0) );
call_method("_gatekeeper", G_VOID|G_DISCARD);
PUTBACK;
FREETMPS;
LEAVE;
}
if (self->fetch_tick > av_len(self->item_cache)) {
/* If empty, return false in both scalar and list context. */
XSRETURN(0);
}
else {
SV *elem = av_delete(self->item_cache, self->fetch_tick, 0);
self->fetch_tick++;
ST(0) = elem;
XSRETURN(1);
}
}
SV*
_get_something(self)
SortExternal *self;
ALIAS:
_get_sortsub = 1
_get_item_cache = 2
_get_runs = 3
_get_tempfile_fh = 4
_get_working_dir = 5
CODE:
{
switch(ix) {
case 1: RETVAL = self->sortsub
? newSVsv(self->sortsub)
: newSV(0);
break;
case 2: RETVAL = newRV_inc((SV*)self->item_cache);
break;
case 3: RETVAL = newRV_inc((SV*)self->runs);
break;
case 4: RETVAL = newSVsv(self->tempfile_fh);
break;
case 5: RETVAL = newSVsv(self->working_dir);
break;
default:
croak("unrecognized alias number %d", ix);
}
}
OUTPUT: RETVAL
void
_set_mem_bytes(self, mem_bytes)
SortExternal *self;
IV mem_bytes;
PPCODE:
self->mem_bytes = mem_bytes;
void
_set_fetch_tick(self, fetch_tick)
SortExternal *self;
IV fetch_tick;
PPCODE:
self->fetch_tick = fetch_tick;
void
_set_temp_fh(self, tempfile_fh)
SortExternal *self;
SV *tempfile_fh;
PPCODE:
SvREFCNT_dec(self->tempfile_fh);
self->tempfile_fh = newSVsv(tempfile_fh);
self->fh = IoIFP( sv_2io(tempfile_fh) );
void
_print_to_sortfile(self, input_av, fh)
SortExternal *self;
AV *input_av;
PerlIO *fh;
PPCODE:
SortEx_print_to_sortfile(self, input_av, fh);
void
_utf8_on(sv)
SV *sv;
PPCODE:
/* Testing only. */
SvUTF8_on(sv);
MODULE = Sort::External PACKAGE = Sort::External::SortExRun
SortExRun*
_new(class_sv, tempfile_fh, start, end)
SV *class_sv;
SV *tempfile_fh;
NV start;
NV end;
CODE:
RETVAL = SortExRun_new(tempfile_fh, start, end);
(void)class_sv; /* Silence "unused var" compiler warning. */
OUTPUT: RETVAL
void
DESTROY(self)
SortExRun *self;
PPCODE:
SortExRun_destroy(self);
SV*
_get_buffarray(self)
SortExRun *self;
CODE:
RETVAL = newRV_inc((SV*)self->buffarray);
OUTPUT: RETVAL
void
_set_buffarray(self, buffarray);
SortExRun *self;
AV *buffarray;
PPCODE:
SvREFCNT_dec((SV*)self->buffarray);
self->buffarray = (AV*)SvREFCNT_inc((SV*)buffarray);
IV
_refill_buffer(self)
SortExRun *self;
CODE:
RETVAL = SortExRun_refill_buffer(self);
OUTPUT: RETVAL
( run in 0.911 second using v1.01-cache-2.11-cpan-5511b514fd6 )