You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2013/07/14 02:14:49 UTC

[lucy-commits] [3/7] git commit: refs/heads/ivars-wip1 - Move BBSortEx out of TestLucy back under Lucy.

Move BBSortEx out of TestLucy back under Lucy.

BBSortEx is a test-only class, but it uses member vars defined in
SortEx.  That's a problem once we cut off access to member vars defined
in another parcel, so move it back under Lucy for the time being.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/ee006ebb
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/ee006ebb
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/ee006ebb

Branch: refs/heads/ivars-wip1
Commit: ee006ebb73e02e72443350fdabc617cd38ee7aaf
Parents: 1e3d2bc
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Fri Jul 12 19:14:18 2013 -0700
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Sat Jul 13 15:17:27 2013 -0700

----------------------------------------------------------------------
 core/Lucy/Test/Util/BBSortEx.c           | 176 --------------------------
 core/Lucy/Test/Util/BBSortEx.cfh         |  58 ---------
 core/Lucy/Util/BBSortEx.c                | 176 ++++++++++++++++++++++++++
 core/Lucy/Util/BBSortEx.cfh              |  58 +++++++++
 perl/buildlib/Lucy/Build/Binding/Misc.pm |  60 ---------
 perl/buildlib/Lucy/Build/Binding/Util.pm |  60 +++++++++
 perl/lib/Lucy/Test/Util/BBSortEx.pm      |  25 ----
 perl/lib/Lucy/Util/BBSortEx.pm           |  25 ++++
 perl/t/015-sort_external.t               |  22 ++--
 perl/t/028-sortexrun.t                   |   2 +-
 10 files changed, 331 insertions(+), 331 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/core/Lucy/Test/Util/BBSortEx.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/BBSortEx.c b/core/Lucy/Test/Util/BBSortEx.c
deleted file mode 100644
index 0e17b42..0000000
--- a/core/Lucy/Test/Util/BBSortEx.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_TESTLUCY_BBSORTEX
-#define TESTLUCY_USE_SHORT_NAMES
-#include "Lucy/Util/ToolSet.h"
-
-#include "Lucy/Test/Util/BBSortEx.h"
-
-#include "Lucy/Index/Segment.h"
-#include "Lucy/Store/InStream.h"
-#include "Lucy/Store/Folder.h"
-#include "Lucy/Store/OutStream.h"
-
-BBSortEx*
-BBSortEx_new(uint32_t mem_threshold, VArray *external) {
-    BBSortEx *self = (BBSortEx*)VTable_Make_Obj(BBSORTEX);
-    return BBSortEx_init(self, mem_threshold, external);
-}
-
-BBSortEx*
-BBSortEx_init(BBSortEx *self, uint32_t mem_threshold, VArray *external) {
-    SortEx_init((SortExternal*)self, sizeof(Obj*));
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-    ivars->external_tick = 0;
-    ivars->external = (VArray*)INCREF(external);
-    ivars->mem_consumed = 0;
-    BBSortEx_Set_Mem_Thresh(self, mem_threshold);
-    return self;
-}
-
-void
-BBSortEx_destroy(BBSortEx *self) {
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-    DECREF(ivars->external);
-    SUPER_DESTROY(self, BBSORTEX);
-}
-
-void
-BBSortEx_clear_cache(BBSortEx *self) {
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-    Obj **const cache = (Obj**)ivars->cache;
-    for (uint32_t i = ivars->cache_tick, max = ivars->cache_max; i < max; i++) {
-        DECREF(cache[i]);
-    }
-    ivars->mem_consumed = 0;
-    BBSortEx_Clear_Cache_t super_clear_cache
-        = SUPER_METHOD_PTR(BBSORTEX, TestLucy_BBSortEx_Clear_Cache);
-    super_clear_cache(self);
-}
-
-void
-BBSortEx_feed(BBSortEx *self, void *data) {
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-    BBSortEx_Feed_t super_feed
-        = SUPER_METHOD_PTR(BBSORTEX, TestLucy_BBSortEx_Feed);
-    super_feed(self, data);
-
-    // Flush() if necessary.
-    ByteBuf *bytebuf = (ByteBuf*)CERTIFY(*(ByteBuf**)data, BYTEBUF);
-    ivars->mem_consumed += BB_Get_Size(bytebuf);
-    if (ivars->mem_consumed >= ivars->mem_thresh) {
-        BBSortEx_Flush(self);
-    }
-}
-
-void
-BBSortEx_flush(BBSortEx *self) {
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-    uint32_t     cache_count = ivars->cache_max - ivars->cache_tick;
-    Obj        **cache = (Obj**)ivars->cache;
-    VArray      *elems;
-
-    if (!cache_count) { return; }
-    else              { elems = VA_new(cache_count); }
-
-    // Sort, then create a new run.
-    BBSortEx_Sort_Cache(self);
-    for (uint32_t i = ivars->cache_tick; i < ivars->cache_max; i++) {
-        VA_Push(elems, cache[i]);
-    }
-    BBSortEx *run = BBSortEx_new(0, elems);
-    DECREF(elems);
-    BBSortEx_Add_Run(self, (SortExternal*)run);
-
-    // Blank the cache vars.
-    ivars->cache_tick += cache_count;
-    BBSortEx_Clear_Cache(self);
-}
-
-uint32_t
-BBSortEx_refill(BBSortEx *self) {
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-
-    // Make sure cache is empty, then set cache tick vars.
-    if (ivars->cache_max - ivars->cache_tick > 0) {
-        THROW(ERR, "Refill called but cache contains %u32 items",
-              ivars->cache_max - ivars->cache_tick);
-    }
-    ivars->cache_tick = 0;
-    ivars->cache_max  = 0;
-
-    // Read in elements.
-    while (1) {
-        ByteBuf *elem = NULL;
-
-        if (ivars->mem_consumed >= ivars->mem_thresh) {
-            ivars->mem_consumed = 0;
-            break;
-        }
-        else if (ivars->external_tick >= VA_Get_Size(ivars->external)) {
-            break;
-        }
-        else {
-            elem = (ByteBuf*)VA_Fetch(ivars->external, ivars->external_tick);
-            ivars->external_tick++;
-            // Should be + sizeof(ByteBuf), but that's ok.
-            ivars->mem_consumed += BB_Get_Size(elem);
-        }
-
-        if (ivars->cache_max == ivars->cache_cap) {
-            BBSortEx_Grow_Cache(self,
-                                Memory_oversize(ivars->cache_max + 1, ivars->width));
-        }
-        Obj **cache = (Obj**)ivars->cache;
-        cache[ivars->cache_max++] = INCREF(elem);
-    }
-
-    return ivars->cache_max;
-}
-
-void
-BBSortEx_flip(BBSortEx *self) {
-    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
-    uint32_t run_mem_thresh = 65536;
-
-    BBSortEx_Flush(self);
-
-    // Recalculate the approximate mem allowed for each run.
-    uint32_t num_runs = VA_Get_Size(ivars->runs);
-    if (num_runs) {
-        run_mem_thresh = (ivars->mem_thresh / 2) / num_runs;
-        if (run_mem_thresh < 65536) {
-            run_mem_thresh = 65536;
-        }
-    }
-
-    for (uint32_t i = 0; i < num_runs; i++) {
-        BBSortEx *run = (BBSortEx*)VA_Fetch(ivars->runs, i);
-        BBSortEx_Set_Mem_Thresh(run, run_mem_thresh);
-    }
-
-    // OK to fetch now.
-    ivars->flipped = true;
-}
-
-int
-BBSortEx_compare(BBSortEx *self, void *va, void *vb) {
-    UNUSED_VAR(self);
-    return BB_compare((ByteBuf**)va, (ByteBuf**)vb);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/core/Lucy/Test/Util/BBSortEx.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/BBSortEx.cfh b/core/Lucy/Test/Util/BBSortEx.cfh
deleted file mode 100644
index 1978085..0000000
--- a/core/Lucy/Test/Util/BBSortEx.cfh
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel TestLucy;
-
-/** SortExternal for ByteBufs.
- */
-
-class Lucy::Test::Util::BBSortEx
-    inherits Lucy::Util::SortExternal {
-
-    VArray   *external;
-    uint32_t  external_tick;
-    uint32_t  mem_consumed;
-
-    inert BBSortEx*
-    new(uint32_t mem_thresh = 0x1000000, VArray *external = NULL);
-
-    inert BBSortEx*
-    init(BBSortEx *self, uint32_t mem_thresh = 0x1000000,
-        VArray *external = NULL);
-
-    void
-    Feed(BBSortEx *self, void *data);
-
-    void
-    Flush(BBSortEx *self);
-
-    uint32_t
-    Refill(BBSortEx *self);
-
-    void
-    Clear_Cache(BBSortEx *self);
-
-    void
-    Flip(BBSortEx *self);
-
-    int
-    Compare(BBSortEx *self, void *va, void *vb);
-
-    public void
-    Destroy(BBSortEx *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/core/Lucy/Util/BBSortEx.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/BBSortEx.c b/core/Lucy/Util/BBSortEx.c
new file mode 100644
index 0000000..d42ca55
--- /dev/null
+++ b/core/Lucy/Util/BBSortEx.c
@@ -0,0 +1,176 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define C_LUCY_BBSORTEX
+#define LUCY_USE_SHORT_NAMES
+#include "Lucy/Util/ToolSet.h"
+
+#include "Lucy/Util/BBSortEx.h"
+
+#include "Lucy/Index/Segment.h"
+#include "Lucy/Store/InStream.h"
+#include "Lucy/Store/Folder.h"
+#include "Lucy/Store/OutStream.h"
+
+BBSortEx*
+BBSortEx_new(uint32_t mem_threshold, VArray *external) {
+    BBSortEx *self = (BBSortEx*)VTable_Make_Obj(BBSORTEX);
+    return BBSortEx_init(self, mem_threshold, external);
+}
+
+BBSortEx*
+BBSortEx_init(BBSortEx *self, uint32_t mem_threshold, VArray *external) {
+    SortEx_init((SortExternal*)self, sizeof(Obj*));
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+    ivars->external_tick = 0;
+    ivars->external = (VArray*)INCREF(external);
+    ivars->mem_consumed = 0;
+    BBSortEx_Set_Mem_Thresh(self, mem_threshold);
+    return self;
+}
+
+void
+BBSortEx_destroy(BBSortEx *self) {
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+    DECREF(ivars->external);
+    SUPER_DESTROY(self, BBSORTEX);
+}
+
+void
+BBSortEx_clear_cache(BBSortEx *self) {
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+    Obj **const cache = (Obj**)ivars->cache;
+    for (uint32_t i = ivars->cache_tick, max = ivars->cache_max; i < max; i++) {
+        DECREF(cache[i]);
+    }
+    ivars->mem_consumed = 0;
+    BBSortEx_Clear_Cache_t super_clear_cache
+        = SUPER_METHOD_PTR(BBSORTEX, Lucy_BBSortEx_Clear_Cache);
+    super_clear_cache(self);
+}
+
+void
+BBSortEx_feed(BBSortEx *self, void *data) {
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+    BBSortEx_Feed_t super_feed
+        = SUPER_METHOD_PTR(BBSORTEX, Lucy_BBSortEx_Feed);
+    super_feed(self, data);
+
+    // Flush() if necessary.
+    ByteBuf *bytebuf = (ByteBuf*)CERTIFY(*(ByteBuf**)data, BYTEBUF);
+    ivars->mem_consumed += BB_Get_Size(bytebuf);
+    if (ivars->mem_consumed >= ivars->mem_thresh) {
+        BBSortEx_Flush(self);
+    }
+}
+
+void
+BBSortEx_flush(BBSortEx *self) {
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+    uint32_t     cache_count = ivars->cache_max - ivars->cache_tick;
+    Obj        **cache = (Obj**)ivars->cache;
+    VArray      *elems;
+
+    if (!cache_count) { return; }
+    else              { elems = VA_new(cache_count); }
+
+    // Sort, then create a new run.
+    BBSortEx_Sort_Cache(self);
+    for (uint32_t i = ivars->cache_tick; i < ivars->cache_max; i++) {
+        VA_Push(elems, cache[i]);
+    }
+    BBSortEx *run = BBSortEx_new(0, elems);
+    DECREF(elems);
+    BBSortEx_Add_Run(self, (SortExternal*)run);
+
+    // Blank the cache vars.
+    ivars->cache_tick += cache_count;
+    BBSortEx_Clear_Cache(self);
+}
+
+uint32_t
+BBSortEx_refill(BBSortEx *self) {
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+
+    // Make sure cache is empty, then set cache tick vars.
+    if (ivars->cache_max - ivars->cache_tick > 0) {
+        THROW(ERR, "Refill called but cache contains %u32 items",
+              ivars->cache_max - ivars->cache_tick);
+    }
+    ivars->cache_tick = 0;
+    ivars->cache_max  = 0;
+
+    // Read in elements.
+    while (1) {
+        ByteBuf *elem = NULL;
+
+        if (ivars->mem_consumed >= ivars->mem_thresh) {
+            ivars->mem_consumed = 0;
+            break;
+        }
+        else if (ivars->external_tick >= VA_Get_Size(ivars->external)) {
+            break;
+        }
+        else {
+            elem = (ByteBuf*)VA_Fetch(ivars->external, ivars->external_tick);
+            ivars->external_tick++;
+            // Should be + sizeof(ByteBuf), but that's ok.
+            ivars->mem_consumed += BB_Get_Size(elem);
+        }
+
+        if (ivars->cache_max == ivars->cache_cap) {
+            BBSortEx_Grow_Cache(self,
+                                Memory_oversize(ivars->cache_max + 1, ivars->width));
+        }
+        Obj **cache = (Obj**)ivars->cache;
+        cache[ivars->cache_max++] = INCREF(elem);
+    }
+
+    return ivars->cache_max;
+}
+
+void
+BBSortEx_flip(BBSortEx *self) {
+    BBSortExIVARS *const ivars = BBSortEx_IVARS(self);
+    uint32_t run_mem_thresh = 65536;
+
+    BBSortEx_Flush(self);
+
+    // Recalculate the approximate mem allowed for each run.
+    uint32_t num_runs = VA_Get_Size(ivars->runs);
+    if (num_runs) {
+        run_mem_thresh = (ivars->mem_thresh / 2) / num_runs;
+        if (run_mem_thresh < 65536) {
+            run_mem_thresh = 65536;
+        }
+    }
+
+    for (uint32_t i = 0; i < num_runs; i++) {
+        BBSortEx *run = (BBSortEx*)VA_Fetch(ivars->runs, i);
+        BBSortEx_Set_Mem_Thresh(run, run_mem_thresh);
+    }
+
+    // OK to fetch now.
+    ivars->flipped = true;
+}
+
+int
+BBSortEx_compare(BBSortEx *self, void *va, void *vb) {
+    UNUSED_VAR(self);
+    return BB_compare((ByteBuf**)va, (ByteBuf**)vb);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/core/Lucy/Util/BBSortEx.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/BBSortEx.cfh b/core/Lucy/Util/BBSortEx.cfh
new file mode 100644
index 0000000..41f72ea
--- /dev/null
+++ b/core/Lucy/Util/BBSortEx.cfh
@@ -0,0 +1,58 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Lucy;
+
+/** SortExternal for ByteBufs.
+ */
+
+class Lucy::Util::BBSortEx
+    inherits Lucy::Util::SortExternal {
+
+    VArray   *external;
+    uint32_t  external_tick;
+    uint32_t  mem_consumed;
+
+    inert BBSortEx*
+    new(uint32_t mem_thresh = 0x1000000, VArray *external = NULL);
+
+    inert BBSortEx*
+    init(BBSortEx *self, uint32_t mem_thresh = 0x1000000,
+        VArray *external = NULL);
+
+    void
+    Feed(BBSortEx *self, void *data);
+
+    void
+    Flush(BBSortEx *self);
+
+    uint32_t
+    Refill(BBSortEx *self);
+
+    void
+    Clear_Cache(BBSortEx *self);
+
+    void
+    Flip(BBSortEx *self);
+
+    int
+    Compare(BBSortEx *self, void *va, void *vb);
+
+    public void
+    Destroy(BBSortEx *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/perl/buildlib/Lucy/Build/Binding/Misc.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Misc.pm b/perl/buildlib/Lucy/Build/Binding/Misc.pm
index 3a779c0..19036d9 100644
--- a/perl/buildlib/Lucy/Build/Binding/Misc.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Misc.pm
@@ -25,7 +25,6 @@ sub bind_all {
     $class->bind_lucy;
     $class->bind_test;
     $class->bind_testschema;
-    $class->bind_bbsortex;
 }
 
 sub inherit_metadata {
@@ -216,64 +215,5 @@ sub bind_testschema {
     Clownfish::CFC::Binding::Perl::Class->register($binding);
 }
 
-sub bind_bbsortex {
-    my @hand_rolled = qw(
-        Fetch
-        Peek
-        Feed
-    );
-    my $xs_code = <<'END_XS_CODE';
-MODULE = Lucy    PACKAGE = Lucy::Test::Util::BBSortEx
-
-SV*
-fetch(self)
-    testlucy_BBSortEx *self;
-CODE:
-{
-    void *address = TestLucy_BBSortEx_Fetch(self);
-    if (address) {
-        RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
-        CFISH_DECREF(*(cfish_Obj**)address);
-    }
-    else {
-        RETVAL = newSV(0);
-    }
-}
-OUTPUT: RETVAL
-
-SV*
-peek(self)
-    testlucy_BBSortEx *self;
-CODE:
-{
-    void *address = TestLucy_BBSortEx_Peek(self);
-    if (address) {
-        RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
-    }
-    else {
-        RETVAL = newSV(0);
-    }
-}
-OUTPUT: RETVAL
-
-void
-feed(self, bb)
-    testlucy_BBSortEx *self;
-    cfish_ByteBuf *bb;
-CODE:
-    CFISH_INCREF(bb);
-    TestLucy_BBSortEx_Feed(self, &bb);
-
-END_XS_CODE
-
-    my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "TestLucy",
-        class_name => "Lucy::Test::Util::BBSortEx",
-    );
-    $binding->append_xs($xs_code);
-
-    Clownfish::CFC::Binding::Perl::Class->register($binding);
-}
-
 1;
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/perl/buildlib/Lucy/Build/Binding/Util.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Util.pm b/perl/buildlib/Lucy/Build/Binding/Util.pm
index df3ee31..a64c58b 100644
--- a/perl/buildlib/Lucy/Build/Binding/Util.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Util.pm
@@ -21,6 +21,7 @@ $VERSION = eval $VERSION;
 
 sub bind_all {
     my $class = shift;
+    $class->bind_bbsortex;
     $class->bind_debug;
     $class->bind_freezer;
     $class->bind_indexfilenames;
@@ -30,6 +31,65 @@ sub bind_all {
     $class->bind_stepper;
 }
 
+sub bind_bbsortex {
+    my @hand_rolled = qw(
+        Fetch
+        Peek
+        Feed
+    );
+    my $xs_code = <<'END_XS_CODE';
+MODULE = Lucy    PACKAGE = Lucy::Util::BBSortEx
+
+SV*
+fetch(self)
+    lucy_BBSortEx *self;
+CODE:
+{
+    void *address = Lucy_BBSortEx_Fetch(self);
+    if (address) {
+        RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
+        CFISH_DECREF(*(cfish_Obj**)address);
+    }
+    else {
+        RETVAL = newSV(0);
+    }
+}
+OUTPUT: RETVAL
+
+SV*
+peek(self)
+    lucy_BBSortEx *self;
+CODE:
+{
+    void *address = Lucy_BBSortEx_Peek(self);
+    if (address) {
+        RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
+    }
+    else {
+        RETVAL = newSV(0);
+    }
+}
+OUTPUT: RETVAL
+
+void
+feed(self, bb)
+    lucy_BBSortEx *self;
+    cfish_ByteBuf *bb;
+CODE:
+    CFISH_INCREF(bb);
+    Lucy_BBSortEx_Feed(self, &bb);
+
+END_XS_CODE
+
+    my $binding = Clownfish::CFC::Binding::Perl::Class->new(
+        parcel     => "Lucy",
+        class_name => "Lucy::Util::BBSortEx",
+    );
+    $binding->append_xs($xs_code);
+
+    Clownfish::CFC::Binding::Perl::Class->register($binding);
+}
+
 sub bind_debug {
     my $xs_code = <<'END_XS_CODE';
 MODULE = Lucy   PACKAGE = Lucy::Util::Debug

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/perl/lib/Lucy/Test/Util/BBSortEx.pm
----------------------------------------------------------------------
diff --git a/perl/lib/Lucy/Test/Util/BBSortEx.pm b/perl/lib/Lucy/Test/Util/BBSortEx.pm
deleted file mode 100644
index 5c968f7..0000000
--- a/perl/lib/Lucy/Test/Util/BBSortEx.pm
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-package Lucy::Test::Util::BBSortEx;
-use Lucy;
-our $VERSION = '0.003000';
-$VERSION = eval $VERSION;
-
-1;
-
-__END__
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/perl/lib/Lucy/Util/BBSortEx.pm
----------------------------------------------------------------------
diff --git a/perl/lib/Lucy/Util/BBSortEx.pm b/perl/lib/Lucy/Util/BBSortEx.pm
new file mode 100644
index 0000000..cbba688
--- /dev/null
+++ b/perl/lib/Lucy/Util/BBSortEx.pm
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package Lucy::Util::BBSortEx;
+use Lucy;
+our $VERSION = '0.003000';
+$VERSION = eval $VERSION;
+
+1;
+
+__END__
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/perl/t/015-sort_external.t
----------------------------------------------------------------------
diff --git a/perl/t/015-sort_external.t b/perl/t/015-sort_external.t
index 4d8bdad..134e7c7 100644
--- a/perl/t/015-sort_external.t
+++ b/perl/t/015-sort_external.t
@@ -23,7 +23,7 @@ use bytes qw();
 
 my ( $sortex, $cache, @orig, @sort_output );
 
-$sortex = Lucy::Test::Util::BBSortEx->new( mem_thresh => 4 );
+$sortex = Lucy::Util::BBSortEx->new( mem_thresh => 4 );
 $sortex->feed( new_bytebuf('c') );
 is( $sortex->cache_count, 1, "feed elem into cache" );
 
@@ -42,7 +42,7 @@ is( $sortex->cache_count, 0,
 #is( $sortex->get_num_runs, 1, "run added" );
 
 my @bytebufs = map { new_bytebuf($_) } qw( x y z );
-my $run = Lucy::Test::Util::BBSortEx->new( external => \@bytebufs );
+my $run = Lucy::Util::BBSortEx->new( external => \@bytebufs );
 $sortex->add_run($run);
 $sortex->flip;
 @orig = qw( a b c d x y z );
@@ -53,7 +53,7 @@ is_deeply( \@sort_output, \@orig, "Add_Run" );
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new( mem_thresh => 4 );
+$sortex = Lucy::Util::BBSortEx->new( mem_thresh => 4 );
 $sortex->feed( new_bytebuf('c') );
 $sortex->clear_cache;
 is( $sortex->cache_count, 0, "Clear_Cache" );
@@ -72,7 +72,7 @@ is_deeply( \@sort_output, \@orig,
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new;
+$sortex = Lucy::Util::BBSortEx->new;
 @orig   = ( 'a' .. 'z' );
 $sortex->feed( new_bytebuf($_) ) for shuffle(@orig);
 $sortex->flip;
@@ -83,7 +83,7 @@ is_deeply( \@sort_output, \@orig, "sort letters" );
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new;
+$sortex = Lucy::Util::BBSortEx->new;
 @orig   = qw( a a a b c d x x x x x x y y );
 $sortex->feed( new_bytebuf($_) ) for shuffle(@orig);
 $sortex->flip;
@@ -94,7 +94,7 @@ is_deeply( \@sort_output, \@orig, "sort repeated letters" );
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new;
+$sortex = Lucy::Util::BBSortEx->new;
 @orig = ( '', '', 'a' .. 'z' );
 $sortex->feed( new_bytebuf($_) ) for shuffle(@orig);
 $sortex->flip;
@@ -105,7 +105,7 @@ is_deeply( \@sort_output, \@orig, "sort letters and empty strings" );
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new( mem_thresh => 30 );
+$sortex = Lucy::Util::BBSortEx->new( mem_thresh => 30 );
 @orig = 'a' .. 'z';
 $sortex->feed( new_bytebuf($_) ) for shuffle(@orig);
 $sortex->flip;
@@ -116,7 +116,7 @@ is_deeply( \@sort_output, \@orig, "... with an absurdly low mem_thresh" );
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new( mem_thresh => 1 );
+$sortex = Lucy::Util::BBSortEx->new( mem_thresh => 1 );
 @orig = 'a' .. 'z';
 $sortex->feed( new_bytebuf($_) ) for shuffle(@orig);
 $sortex->flip;
@@ -127,13 +127,13 @@ is_deeply( \@sort_output, \@orig, "... with an even lower mem_thresh" );
 @orig        = ();
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new;
+$sortex = Lucy::Util::BBSortEx->new;
 $sortex->flip;
 @sort_output = $sortex->fetch;
 is_deeply( \@sort_output, [undef], "Sorting nothing returns undef" );
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new( mem_thresh => 5_000 );
+$sortex = Lucy::Util::BBSortEx->new( mem_thresh => 5_000 );
 @orig = map { pack( 'N', $_ ) } ( 0 .. 11_000 );
 $sortex->feed( new_bytebuf($_) ) for shuffle(@orig);
 $sortex->flip;
@@ -143,7 +143,7 @@ while ( defined( my $item = $sortex->fetch ) ) {
 is_deeply( \@sort_output, \@orig, "Sorting packed integers..." );
 @sort_output = ();
 
-$sortex = Lucy::Test::Util::BBSortEx->new( mem_thresh => 15_000 );
+$sortex = Lucy::Util::BBSortEx->new( mem_thresh => 15_000 );
 @orig = ();
 for my $iter ( 0 .. 1_000 ) {
     my $string = '';

http://git-wip-us.apache.org/repos/asf/lucy/blob/ee006ebb/perl/t/028-sortexrun.t
----------------------------------------------------------------------
diff --git a/perl/t/028-sortexrun.t b/perl/t/028-sortexrun.t
index 64b9ef7..a9a075b 100644
--- a/perl/t/028-sortexrun.t
+++ b/perl/t/028-sortexrun.t
@@ -24,7 +24,7 @@ use Clownfish qw( to_perl );
 
 my $letters = Clownfish::VArray->new( capacity => 26 );
 $letters->push( Clownfish::ByteBuf->new($_) ) for 'a' .. 'z';
-my $run = Lucy::Test::Util::BBSortEx->new( external => $letters );
+my $run = Lucy::Util::BBSortEx->new( external => $letters );
 $run->set_mem_thresh(5);
 
 my $num_in_cache = $run->refill;