LCOV - code coverage report
Current view: top level - gdk - gdk_orderidx.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 109 225 48.4 %
Date: 2021-09-14 19:48:19 Functions: 7 8 87.5 %

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

Generated by: LCOV version 1.14