LCOV - code coverage report
Current view: top level - gdk - gdk_orderidx.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 95 260 36.5 %
Date: 2024-11-12 19:36:54 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "gdk.h"
      15             : #include "gdk_private.h"
      16             : 
      17             : #define ORDERIDX_VERSION        ((oid) 3)
      18             : 
      19             : #ifdef PERSISTENTIDX
      20             : static void
      21           6 : BATidxsync(void *arg)
      22             : {
      23           6 :         BAT *b = arg;
      24           6 :         Heap *hp;
      25           6 :         int fd;
      26           6 :         lng t0  = GDKusec();
      27           6 :         const char *failed = " failed";
      28             : 
      29             : 
      30           6 :         MT_lock_set(&b->batIdxLock);
      31           6 :         if ((hp = b->torderidx) != NULL) {
      32           6 :                 if (HEAPsave(hp, hp->filename, NULL, true, hp->free, NULL) == GDK_SUCCEED) {
      33           6 :                         if (hp->storage == STORE_MEM) {
      34           6 :                                 if ((fd = GDKfdlocate(hp->farmid, hp->filename, "rb+", NULL)) >= 0) {
      35           6 :                                         ((oid *) hp->base)[0] |= (oid) 1 << 24;
      36           6 :                                         if (write(fd, hp->base, SIZEOF_OID) >= 0) {
      37           6 :                                                 failed = ""; /* not failed */
      38           6 :                                                 if (!(ATOMIC_GET(&GDKdebug) & NOSYNCMASK)) {
      39             : #if defined(NATIVE_WIN32)
      40             :                                                         _commit(fd);
      41             : #elif defined(HAVE_FDATASYNC)
      42           0 :                                                         fdatasync(fd);
      43             : #elif defined(HAVE_FSYNC)
      44             :                                                         fsync(fd);
      45             : #endif
      46             :                                                 }
      47           6 :                                                 hp->dirty = false;
      48             :                                         } else {
      49           0 :                                                 perror("write hash");
      50             :                                         }
      51           6 :                                         close(fd);
      52             :                                 }
      53             :                         } else {
      54           0 :                                 ((oid *) hp->base)[0] |= (oid) 1 << 24;
      55           0 :                                 if (!(ATOMIC_GET(&GDKdebug) & NOSYNCMASK) &&
      56           0 :                                     MT_msync(hp->base, SIZEOF_OID) < 0) {
      57           0 :                                         ((oid *) hp->base)[0] &= ~((oid) 1 << 24);
      58             :                                 } else {
      59           0 :                                         hp->dirty = false;
      60           0 :                                         failed = ""; /* not failed */
      61             :                                 }
      62             :                         }
      63           6 :                         TRC_DEBUG(ACCELERATOR, "BATidxsync(%s): orderidx persisted"
      64             :                                   " (" LLFMT " usec)%s\n",
      65             :                                   BATgetId(b), GDKusec() - t0, failed);
      66             :                 }
      67             :         }
      68           6 :         MT_lock_unset(&b->batIdxLock);
      69           6 :         BBPunfix(b->batCacheid);
      70           6 : }
      71             : #endif
      72             : 
      73             : /* return TRUE if we have a orderidx on the tail, even if we need to read
      74             :  * one from disk */
      75             : bool
      76     1901110 : BATcheckorderidx(BAT *b)
      77             : {
      78     1901110 :         bool ret;
      79     1901110 :         lng t = GDKusec();
      80             : 
      81     1901326 :         if (b == NULL)
      82             :                 return false;
      83     1901326 :         MT_lock_set(&b->batIdxLock);
      84     1901300 :         if (b->torderidx == (Heap *) 1) {
      85           0 :                 Heap *hp;
      86           0 :                 const char *nme = BBP_physical(b->batCacheid);
      87           0 :                 int fd;
      88             : 
      89           0 :                 assert(!GDKinmemory(b->theap->farmid));
      90           0 :                 b->torderidx = NULL;
      91           0 :                 if ((hp = GDKzalloc(sizeof(*hp))) != NULL &&
      92           0 :                     (hp->farmid = BBPselectfarm(b->batRole, b->ttype, orderidxheap)) >= 0) {
      93           0 :                         strconcat_len(hp->filename,
      94             :                                       sizeof(hp->filename),
      95             :                                       nme, ".torderidx", NULL);
      96           0 :                         hp->storage = hp->newstorage = STORE_INVALID;
      97             : 
      98             :                         /* check whether a persisted orderidx can be found */
      99           0 :                         if ((fd = GDKfdlocate(hp->farmid, nme, "rb+", "torderidx")) >= 0) {
     100           0 :                                 struct stat st;
     101           0 :                                 oid hdata[ORDERIDXOFF];
     102             : 
     103           0 :                                 if (read(fd, hdata, sizeof(hdata)) == sizeof(hdata) &&
     104           0 :                                     hdata[0] == (
     105             : #ifdef PERSISTENTIDX
     106             :                                             ((oid) 1 << 24) |
     107             : #endif
     108           0 :                                             ORDERIDX_VERSION) &&
     109           0 :                                     hdata[1] == (oid) BATcount(b) &&
     110           0 :                                     (hdata[2] == 0 || hdata[2] == 1) &&
     111           0 :                                     fstat(fd, &st) == 0 &&
     112           0 :                                     st.st_size >= (off_t) (hp->size = hp->free = (ORDERIDXOFF + hdata[1]) * SIZEOF_OID) &&
     113           0 :                                     HEAPload(hp, nme, "torderidx", false) == GDK_SUCCEED) {
     114           0 :                                         close(fd);
     115           0 :                                         ATOMIC_INIT(&hp->refs, 1);
     116           0 :                                         b->torderidx = hp;
     117           0 :                                         hp->hasfile = true;
     118           0 :                                         TRC_DEBUG(ACCELERATOR, "BATcheckorderidx(" ALGOBATFMT "): reusing persisted orderidx\n", ALGOBATPAR(b));
     119           0 :                                         MT_lock_unset(&b->batIdxLock);
     120           0 :                                         return true;
     121             :                                 }
     122           0 :                                 close(fd);
     123             :                                 /* unlink unusable file */
     124           0 :                                 GDKunlink(hp->farmid, BATDIR, nme, "torderidx");
     125           0 :                                 hp->hasfile = false;
     126             :                         }
     127             :                 }
     128           0 :                 GDKfree(hp);
     129           0 :                 GDKclrerr();    /* we're not currently interested in errors */
     130             :         }
     131     1901300 :         MT_lock_unset(&b->batIdxLock);
     132             : 
     133     1901635 :         ret = b->torderidx != NULL;
     134     1901635 :         if (ret)
     135         114 :                 TRC_DEBUG(ACCELERATOR, "BATcheckorderidx(" ALGOBATFMT "): already has orderidx, waited " LLFMT " usec\n", ALGOBATPAR(b), GDKusec() - t);
     136             :         return ret;
     137             : }
     138             : 
     139             : /* create the heap for an order index; returns NULL on failure */
     140             : Heap *
     141        4386 : createOIDXheap(BAT *b, bool stable)
     142             : {
     143        4386 :         Heap *m;
     144        4386 :         oid *restrict mv;
     145             : 
     146        4386 :         if ((m = GDKmalloc(sizeof(Heap))) == NULL)
     147             :                 return NULL;
     148        8776 :         *m = (Heap) {
     149        4388 :                 .farmid = BBPselectfarm(b->batRole, b->ttype, orderidxheap),
     150        4388 :                 .parentid = b->batCacheid,
     151             :                 .dirty = true,
     152             :                 .refs = ATOMIC_VAR_INIT(1),
     153             :         };
     154        4388 :         strconcat_len(m->filename, sizeof(m->filename),
     155        4388 :                       BBP_physical(b->batCacheid), ".torderidx", NULL);
     156        8778 :         if (m->farmid < 0 ||
     157        4389 :             HEAPalloc(m, BATcount(b) + ORDERIDXOFF, SIZEOF_OID) != GDK_SUCCEED) {
     158           0 :                 GDKfree(m);
     159           0 :                 return NULL;
     160             :         }
     161        4389 :         m->free = (BATcount(b) + ORDERIDXOFF) * SIZEOF_OID;
     162             : 
     163        4389 :         mv = (oid *) m->base;
     164        4389 :         *mv++ = ORDERIDX_VERSION;
     165        4389 :         *mv++ = (oid) BATcount(b);
     166        4389 :         *mv++ = (oid) stable;
     167        4389 :         return m;
     168             : }
     169             : 
     170             : /* maybe persist the order index heap */
     171             : void
     172        4388 : persistOIDX(BAT *b)
     173             : {
     174             : #ifdef PERSISTENTIDX
     175        4388 :         if ((BBP_status(b->batCacheid) & BBPEXISTING) &&
     176           8 :             b->batInserted == b->batCount &&
     177          12 :             !b->theap->dirty &&
     178          12 :             !GDKinmemory(b->theap->farmid)) {
     179           6 :                 MT_Id tid;
     180           6 :                 BBPfix(b->batCacheid);
     181           6 :                 char name[MT_NAME_LEN];
     182           6 :                 snprintf(name, sizeof(name), "oidxsync%d", b->batCacheid);
     183           6 :                 if (MT_create_thread(&tid, BATidxsync, b,
     184             :                                      MT_THR_DETACHED, name) < 0)
     185           0 :                         BBPunfix(b->batCacheid);
     186             :         } else
     187        4382 :                 TRC_DEBUG(ACCELERATOR, "persistOIDX(" ALGOBATFMT "): NOT persisting order index\n", ALGOBATPAR(b));
     188             : #else
     189             :         (void) b;
     190             : #endif
     191        4388 : }
     192             : 
     193             : gdk_return
     194          73 : BATorderidx(BAT *b, bool stable)
     195             : {
     196          73 :         if (b->ttype == TYPE_void) {
     197           0 :                 GDKerror("No order index on void type bats\n");
     198           0 :                 return GDK_FAIL;
     199             :         }
     200          73 :         if (BATcheckorderidx(b))
     201             :                 return GDK_SUCCEED;
     202          73 :         if (!BATtdense(b)) {
     203          73 :                 BAT *on;
     204          73 :                 MT_thread_setalgorithm("create order index");
     205          73 :                 TRC_DEBUG(ACCELERATOR, "BATorderidx(" ALGOBATFMT ",%d) create index\n", ALGOBATPAR(b), stable);
     206          73 :                 if (BATsort(NULL, &on, NULL, b, NULL, NULL, false, false, stable) != GDK_SUCCEED)
     207           0 :                         return GDK_FAIL;
     208          73 :                 assert(BATcount(b) == BATcount(on));
     209          73 :                 if (BATtdense(on)) {
     210             :                         /* if the order bat is dense, the input was
     211             :                          * sorted and we don't need an order index */
     212           0 :                         MT_lock_set(&b->theaplock);
     213           0 :                         assert(!b->tnosorted);
     214           0 :                         if (!b->tsorted) {
     215           0 :                                 b->tsorted = true;
     216           0 :                                 b->tnosorted = 0;
     217             :                         }
     218           0 :                         MT_lock_unset(&b->theaplock);
     219             :                 } else {
     220             :                         /* BATsort quite possibly already created the
     221             :                          * order index, but just to be sure... */
     222          73 :                         MT_lock_set(&b->batIdxLock);
     223          73 :                         if (b->torderidx == NULL) {
     224           0 :                                 Heap *m;
     225           0 :                                 if ((m = createOIDXheap(b, stable)) == NULL) {
     226           0 :                                         MT_lock_unset(&b->batIdxLock);
     227           0 :                                         return GDK_FAIL;
     228             :                                 }
     229           0 :                                 memcpy((oid *) m->base + ORDERIDXOFF, Tloc(on, 0), BATcount(on) * sizeof(oid));
     230           0 :                                 b->torderidx = m;
     231           0 :                                 persistOIDX(b);
     232             :                         }
     233          73 :                         MT_lock_unset(&b->batIdxLock);
     234             :                 }
     235          73 :                 BBPunfix(on->batCacheid);
     236             :         }
     237             :         return GDK_SUCCEED;
     238             : }
     239             : 
     240             : #define BINARY_MERGE(TYPE)                                              \
     241             :         do {                                                            \
     242             :                 TYPE *v = (TYPE *) bi.base;                             \
     243             :                 if (p0 < q0 && p1 < q1) {                         \
     244             :                         if (v[*p0 - b->hseqbase] <= v[*p1 - b->hseqbase]) { \
     245             :                                 *mv++ = *p0++;                          \
     246             :                         } else {                                        \
     247             :                                 *mv++ = *p1++;                          \
     248             :                         }                                               \
     249             :                 } else if (p0 < q0) {                                        \
     250             :                         assert(p1 == q1);                               \
     251             :                         *mv++ = *p0++;                                  \
     252             :                 } else if (p1 < q1) {                                        \
     253             :                         assert(p0 == q0);                               \
     254             :                         *mv++ = *p1++;                                  \
     255             :                 } else {                                                \
     256             :                         assert(p0 == q0 && p1 == q1);                   \
     257             :                         break;                                          \
     258             :                 }                                                       \
     259             :                 while (p0 < q0 && p1 < q1) {                              \
     260             :                         if (v[*p0 - b->hseqbase] <= v[*p1 - b->hseqbase]) { \
     261             :                                 *mv++ = *p0++;                          \
     262             :                         } else {                                        \
     263             :                                 *mv++ = *p1++;                          \
     264             :                         }                                               \
     265             :                 }                                                       \
     266             :                 while (p0 < q0) {                                    \
     267             :                         *mv++ = *p0++;                                  \
     268             :                 }                                                       \
     269             :                 while (p1 < q1) {                                    \
     270             :                         *mv++ = *p1++;                                  \
     271             :                 }                                                       \
     272             :         } while(0)
     273             : 
     274             : #define swap(X,Y,TMP)  (TMP)=(X);(X)=(Y);(Y)=(TMP)
     275             : 
     276             : #define left_child(X)  (2*(X)+1)
     277             : #define right_child(X) (2*(X)+2)
     278             : 
     279             : #define HEAPIFY(X)                                                      \
     280             :         do {                                                            \
     281             :                 int cur, min = X, chld;                                 \
     282             :                 do {                                                    \
     283             :                         cur = min;                                      \
     284             :                         if ((chld = left_child(cur)) < n_ar &&               \
     285             :                             (minhp[chld] < minhp[min] ||             \
     286             :                              (minhp[chld] == minhp[min] &&              \
     287             :                               *p[cur] < *p[min]))) {                 \
     288             :                                 min = chld;                             \
     289             :                         }                                               \
     290             :                         if ((chld = right_child(cur)) < n_ar &&              \
     291             :                             (minhp[chld] < minhp[min] ||             \
     292             :                              (minhp[chld] == minhp[min] &&              \
     293             :                               *p[cur] < *p[min]))) {                 \
     294             :                                 min = chld;                             \
     295             :                         }                                               \
     296             :                         if (min != cur) {                               \
     297             :                                 swap(minhp[cur], minhp[min], t);        \
     298             :                                 swap(p[cur], p[min], t_oid);            \
     299             :                                 swap(q[cur], q[min], t_oid);            \
     300             :                         }                                               \
     301             :                 } while (cur != min);                                   \
     302             :         } while (0)
     303             : 
     304             : #define NWAY_MERGE(TYPE)                                                \
     305             :         do {                                                            \
     306             :                 TYPE *minhp, t;                                         \
     307             :                 TYPE *v = (TYPE *) bi.base;                             \
     308             :                 if ((minhp = GDKmalloc(sizeof(TYPE)*n_ar)) == NULL) {   \
     309             :                         goto bailout;                                   \
     310             :                 }                                                       \
     311             :                 /* init min heap */                                     \
     312             :                 for (i = 0; i < n_ar; i++) {                         \
     313             :                         minhp[i] = v[*p[i] - b->hseqbase];           \
     314             :                 }                                                       \
     315             :                 for (i = n_ar/2; i >=0 ; i--) {                              \
     316             :                         HEAPIFY(i);                                     \
     317             :                 }                                                       \
     318             :                 /* merge */                                             \
     319             :                 *mv++ = *(p[0])++;                                      \
     320             :                 if (p[0] < q[0]) {                                   \
     321             :                         minhp[0] = v[*p[0] - b->hseqbase];           \
     322             :                         HEAPIFY(0);                                     \
     323             :                 } else {                                                \
     324             :                         swap(minhp[0], minhp[n_ar-1], t);               \
     325             :                         swap(p[0], p[n_ar-1], t_oid);                   \
     326             :                         swap(q[0], q[n_ar-1], t_oid);                   \
     327             :                         n_ar--;                                         \
     328             :                         HEAPIFY(0);                                     \
     329             :                 }                                                       \
     330             :                 while (n_ar > 1) {                                   \
     331             :                         *mv++ = *(p[0])++;                              \
     332             :                         if (p[0] < q[0]) {                           \
     333             :                                 minhp[0] = v[*p[0] - b->hseqbase];   \
     334             :                                 HEAPIFY(0);                             \
     335             :                         } else {                                        \
     336             :                                 swap(minhp[0], minhp[n_ar-1], t);       \
     337             :                                 swap(p[0], p[n_ar-1], t_oid);           \
     338             :                                 swap(q[0], q[n_ar-1], t_oid);           \
     339             :                                 n_ar--;                                 \
     340             :                                 HEAPIFY(0);                             \
     341             :                         }                                               \
     342             :                 }                                                       \
     343             :                 while (p[0] < q[0]) {                                        \
     344             :                         *mv++ = *(p[0])++;                              \
     345             :                 }                                                       \
     346             :                 GDKfree(minhp);                                         \
     347             :         } while (0)
     348             : 
     349             : gdk_return
     350           0 : GDKmergeidx(BAT *b, BAT**a, int n_ar)
     351             : {
     352           0 :         Heap *m;
     353           0 :         int i;
     354           0 :         oid *restrict mv;
     355           0 :         const char *nme = BBP_physical(b->batCacheid);
     356             : 
     357           0 :         if (BATcheckorderidx(b))
     358             :                 return GDK_SUCCEED;
     359           0 :         switch (ATOMbasetype(b->ttype)) {
     360             :         case TYPE_bte:
     361             :         case TYPE_sht:
     362             :         case TYPE_int:
     363             :         case TYPE_lng:
     364             : #ifdef HAVE_HGE
     365             :         case TYPE_hge:
     366             : #endif
     367             :         case TYPE_flt:
     368             :         case TYPE_dbl:
     369           0 :                 break;
     370           0 :         default:
     371           0 :                 GDKerror("type %s not supported.\n", ATOMname(b->ttype));
     372           0 :                 return GDK_FAIL;
     373             :         }
     374           0 :         TRC_DEBUG(ACCELERATOR, "GDKmergeidx(" ALGOBATFMT ") create index\n", ALGOBATPAR(b));
     375           0 :         BATiter bi = bat_iterator(b);
     376           0 :         MT_lock_set(&b->batIdxLock);
     377           0 :         if (b->torderidx) {
     378           0 :                 MT_lock_unset(&b->batIdxLock);
     379           0 :                 bat_iterator_end(&bi);
     380           0 :                 return GDK_SUCCEED;
     381             :         }
     382           0 :         if ((m = GDKmalloc(sizeof(Heap))) == NULL) {
     383           0 :                 MT_lock_unset(&b->batIdxLock);
     384           0 :                 bat_iterator_end(&bi);
     385           0 :                 return GDK_FAIL;
     386             :         }
     387           0 :         *m = (Heap) {
     388           0 :                 .farmid = BBPselectfarm(b->batRole, bi.type, orderidxheap),
     389           0 :                 .parentid = b->batCacheid,
     390             :                 .dirty = true,
     391             :                 .refs = ATOMIC_VAR_INIT(1),
     392             :         };
     393           0 :         strconcat_len(m->filename, sizeof(m->filename),
     394             :                       nme, ".torderidx", NULL);
     395           0 :         if (m->farmid < 0 ||
     396           0 :             HEAPalloc(m, BATcount(b) + ORDERIDXOFF, SIZEOF_OID) != GDK_SUCCEED) {
     397           0 :                 GDKfree(m);
     398           0 :                 MT_lock_unset(&b->batIdxLock);
     399           0 :                 bat_iterator_end(&bi);
     400           0 :                 return GDK_FAIL;
     401             :         }
     402           0 :         m->free = (BATcount(b) + ORDERIDXOFF) * SIZEOF_OID;
     403             : 
     404           0 :         mv = (oid *) m->base;
     405           0 :         *mv++ = ORDERIDX_VERSION;
     406           0 :         *mv++ = (oid) BATcount(b);
     407             :         /* all participating indexes must be stable for the combined
     408             :          * index to be stable */
     409           0 :         *mv = 1;
     410           0 :         for (i = 0; i < n_ar; i++) {
     411           0 :                 if ((*mv &= ((const oid *) a[i]->torderidx->base)[2]) == 0)
     412             :                         break;
     413             :         }
     414           0 :         mv++;
     415             : 
     416           0 :         if (n_ar == 1) {
     417             :                 /* One oid order bat, nothing to merge */
     418           0 :                 assert(BATcount(a[0]) == BATcount(b));
     419           0 :                 assert((VIEWtparent(a[0]) == b->batCacheid ||
     420             :                         VIEWtparent(a[0]) == VIEWtparent(b)) &&
     421             :                        a[0]->torderidx);
     422           0 :                 memcpy(mv, (const oid *) a[0]->torderidx->base + ORDERIDXOFF,
     423             :                        BATcount(a[0]) * SIZEOF_OID);
     424           0 :         } else if (n_ar == 2) {
     425             :                 /* sort merge with 1 comparison per BUN */
     426           0 :                 const oid *restrict p0, *restrict p1, *q0, *q1;
     427           0 :                 assert(BATcount(a[0]) + BATcount(a[1]) == BATcount(b));
     428           0 :                 assert((VIEWtparent(a[0]) == b->batCacheid ||
     429             :                         VIEWtparent(a[0]) == VIEWtparent(b)) &&
     430             :                        a[0]->torderidx);
     431           0 :                 assert((VIEWtparent(a[1]) == b->batCacheid ||
     432             :                         VIEWtparent(a[1]) == VIEWtparent(b)) &&
     433             :                        a[1]->torderidx);
     434           0 :                 p0 = (const oid *) a[0]->torderidx->base + ORDERIDXOFF;
     435           0 :                 p1 = (const oid *) a[1]->torderidx->base + ORDERIDXOFF;
     436           0 :                 q0 = p0 + BATcount(a[0]);
     437           0 :                 q1 = p1 + BATcount(a[1]);
     438             : 
     439           0 :                 switch (ATOMbasetype(bi.type)) {
     440           0 :                 case TYPE_bte: BINARY_MERGE(bte); break;
     441           0 :                 case TYPE_sht: BINARY_MERGE(sht); break;
     442           0 :                 case TYPE_int: BINARY_MERGE(int); break;
     443           0 :                 case TYPE_lng: BINARY_MERGE(lng); break;
     444             : #ifdef HAVE_HGE
     445           0 :                 case TYPE_hge: BINARY_MERGE(hge); break;
     446             : #endif
     447           0 :                 case TYPE_flt: BINARY_MERGE(flt); break;
     448           0 :                 case TYPE_dbl: BINARY_MERGE(dbl); break;
     449             :                 default:
     450             :                         /* TODO: support strings, date, timestamps etc. */
     451           0 :                         assert(0);
     452             :                         HEAPfree(m, true);
     453             :                         GDKfree(m);
     454             :                         MT_lock_unset(&b->batIdxLock);
     455             :                         bat_iterator_end(&bi);
     456             :                         return GDK_FAIL;
     457             :                 }
     458             : 
     459             :         } else {
     460             :                 /* use min-heap */
     461           0 :                 oid **p, **q, *t_oid;
     462             : 
     463           0 :                 p = GDKmalloc(n_ar*sizeof(oid *));
     464           0 :                 q = GDKmalloc(n_ar*sizeof(oid *));
     465           0 :                 if (p == NULL || q == NULL) {
     466           0 :                   bailout:
     467           0 :                         GDKfree(p);
     468           0 :                         GDKfree(q);
     469           0 :                         HEAPfree(m, true);
     470           0 :                         GDKfree(m);
     471           0 :                         MT_lock_unset(&b->batIdxLock);
     472           0 :                         bat_iterator_end(&bi);
     473           0 :                         return GDK_FAIL;
     474             :                 }
     475           0 :                 for (i = 0; i < n_ar; i++) {
     476           0 :                         assert((VIEWtparent(a[i]) == b->batCacheid ||
     477             :                                 VIEWtparent(a[i]) == VIEWtparent(b)) &&
     478             :                                a[i]->torderidx);
     479           0 :                         p[i] = (oid *) a[i]->torderidx->base + ORDERIDXOFF;
     480           0 :                         q[i] = p[i] + BATcount(a[i]);
     481             :                 }
     482             : 
     483           0 :                 switch (ATOMbasetype(bi.type)) {
     484           0 :                 case TYPE_bte: NWAY_MERGE(bte); break;
     485           0 :                 case TYPE_sht: NWAY_MERGE(sht); break;
     486           0 :                 case TYPE_int: NWAY_MERGE(int); break;
     487           0 :                 case TYPE_lng: NWAY_MERGE(lng); break;
     488             : #ifdef HAVE_HGE
     489           0 :                 case TYPE_hge: NWAY_MERGE(hge); break;
     490             : #endif
     491           0 :                 case TYPE_flt: NWAY_MERGE(flt); break;
     492           0 :                 case TYPE_dbl: NWAY_MERGE(dbl); break;
     493             :                 case TYPE_void:
     494             :                 case TYPE_str:
     495             :                 case TYPE_ptr:
     496             :                 default:
     497             :                         /* TODO: support strings, date, timestamps etc. */
     498           0 :                         assert(0);
     499             :                         goto bailout;
     500             :                 }
     501           0 :                 GDKfree(p);
     502           0 :                 GDKfree(q);
     503             :         }
     504             : 
     505           0 :         b->torderidx = m;
     506             : #ifdef PERSISTENTIDX
     507           0 :         if ((BBP_status(b->batCacheid) & BBPEXISTING) &&
     508           0 :             b->batInserted == b->batCount) {
     509           0 :                 MT_Id tid;
     510           0 :                 BBPfix(b->batCacheid);
     511           0 :                 char name[MT_NAME_LEN];
     512           0 :                 snprintf(name, sizeof(name), "oidxsync%d", b->batCacheid);
     513           0 :                 if (MT_create_thread(&tid, BATidxsync, b,
     514             :                                      MT_THR_DETACHED, name) < 0)
     515           0 :                         BBPunfix(b->batCacheid);
     516             :         } else
     517           0 :                 TRC_DEBUG(ACCELERATOR, "GDKmergeidx(%s): NOT persisting index\n", BATgetId(b));
     518             : #endif
     519             : 
     520           0 :         MT_lock_unset(&b->batIdxLock);
     521           0 :         bat_iterator_end(&bi);
     522           0 :         return GDK_SUCCEED;
     523             : }
     524             : 
     525             : void
     526      568228 : OIDXfree(BAT *b)
     527             : {
     528      568228 :         if (b) {
     529      568228 :                 Heap *hp;
     530             : 
     531      568228 :                 MT_lock_set(&b->batIdxLock);
     532      568228 :                 if ((hp = b->torderidx) != NULL && hp != (Heap *) 1) {
     533           3 :                         if (GDKinmemory(b->theap->farmid)) {
     534           0 :                                 b->torderidx = NULL;
     535           0 :                                 HEAPdecref(hp, true);
     536             :                         } else {
     537           3 :                                 b->torderidx = (Heap *) 1;
     538           3 :                                 HEAPdecref(hp, false);
     539             :                         }
     540             :                 }
     541      568228 :                 MT_lock_unset(&b->batIdxLock);
     542             :         }
     543      568228 : }
     544             : 
     545             : void
     546    79811038 : OIDXdestroy(BAT *b)
     547             : {
     548    79811038 :         if (b) {
     549    79811038 :                 Heap *hp;
     550             : 
     551    79811038 :                 MT_lock_set(&b->batIdxLock);
     552    79800777 :                 hp = b->torderidx;
     553    79800777 :                 b->torderidx = NULL;
     554    79800777 :                 MT_lock_unset(&b->batIdxLock);
     555    79887112 :                 if (hp == (Heap *) 1) {
     556           0 :                         GDKunlink(BBPselectfarm(b->batRole, b->ttype, orderidxheap),
     557             :                                   BATDIR,
     558           0 :                                   BBP_physical(b->batCacheid),
     559             :                                   "torderidx");
     560    79887112 :                 } else if (hp != NULL) {
     561        4386 :                         HEAPdecref(hp, true);
     562             :                 }
     563             :         }
     564    79887109 : }

Generated by: LCOV version 1.14