tlosertree.c 3.8 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

S
Shengliang Guan 已提交
16
#define _DEFAULT_SOURCE
H
Haojun Liao 已提交
17 18
#include "tlosertree.h"
#include "taoserror.h"
S
Shengliang Guan 已提交
19
#include "tlog.h"
H
hzcheng 已提交
20

21 22 23 24 25 26
// Set the initial value of the multiway merge tree.
static void tMergeTreeInit(SMultiwayMergeTreeInfo* pTree) {
  assert((pTree->totalSources & 0x01) == 0 && (pTree->numOfSources << 1 == pTree->totalSources));

  for (int32_t i = 0; i < pTree->totalSources; ++i) {
    if (i < pTree->numOfSources) {
H
hzcheng 已提交
27 28
      pTree->pNode[i].index = -1;
    } else {
29
      pTree->pNode[i].index = i - pTree->numOfSources;
H
hzcheng 已提交
30 31 32 33
    }
  }
}

S
Shengliang Guan 已提交
34 35
int32_t tMergeTreeCreate(SMultiwayMergeTreeInfo** pTree, uint32_t numOfSources, void* param,
                         __merge_compare_fn_t compareFn) {
36
  int32_t totalEntries = numOfSources << 1u;
H
hzcheng 已提交
37

S
Shengliang Guan 已提交
38 39
  SMultiwayMergeTreeInfo* pTreeInfo =
      (SMultiwayMergeTreeInfo*)calloc(1, sizeof(SMultiwayMergeTreeInfo) + sizeof(STreeNode) * totalEntries);
H
Haojun Liao 已提交
40
  if (pTreeInfo == NULL) {
41
    uError("allocate memory for loser-tree failed. reason:%s", strerror(errno));
H
Haojun Liao 已提交
42
    return TAOS_SYSTEM_ERROR(errno);
H
hzcheng 已提交
43 44
  }

H
Haojun Liao 已提交
45
  pTreeInfo->pNode = (STreeNode*)(((char*)pTreeInfo) + sizeof(SMultiwayMergeTreeInfo));
H
hzcheng 已提交
46

47 48 49 50
  pTreeInfo->numOfSources = numOfSources;
  pTreeInfo->totalSources = totalEntries;
  pTreeInfo->param = param;
  pTreeInfo->comparFn = compareFn;
H
hzcheng 已提交
51 52

  // set initial value for loser tree
53
  tMergeTreeInit(pTreeInfo);
H
hzcheng 已提交
54 55 56

#ifdef _DEBUG_VIEW
  printf("the initial value of loser tree:\n");
57
  tLoserTreeDisplaypTreeInfo;
H
hzcheng 已提交
58 59
#endif

60
  for (int32_t i = totalEntries - 1; i >= numOfSources; i--) {
61
    tMergeTreeAdjust(pTreeInfo, i);
H
hzcheng 已提交
62 63 64 65
  }

#if defined(_DEBUG_VIEW)
  printf("after adjust:\n");
66
  tLoserTreeDisplaypTreeInfo;
H
hzcheng 已提交
67 68 69
  printf("initialize local reducer completed!\n");
#endif

70
  *pTree = pTreeInfo;
71
  return 0;
H
hzcheng 已提交
72 73
}

H
Haojun Liao 已提交
74 75 76 77 78 79 80 81
void tMergeTreeDestroy(SMultiwayMergeTreeInfo* pTree) {
  if (pTree == NULL) {
    return;
  }

  tfree(pTree);
}

82 83
void tMergeTreeAdjust(SMultiwayMergeTreeInfo* pTree, int32_t idx) {
  assert(idx <= pTree->totalSources - 1 && idx >= pTree->numOfSources && pTree->totalSources >= 2);
H
hzcheng 已提交
84

85
  if (pTree->totalSources == 2) {
H
hzcheng 已提交
86 87 88 89 90
    pTree->pNode[0].index = 0;
    pTree->pNode[1].index = 0;
    return;
  }

S
Shengliang Guan 已提交
91
  int32_t   parentId = idx >> 1;
92
  STreeNode kLeaf = pTree->pNode[idx];
H
hzcheng 已提交
93 94

  while (parentId > 0) {
95
    STreeNode* pCur = &pTree->pNode[parentId];
H
Haojun Liao 已提交
96
    if (pCur->index == -1) {
H
hzcheng 已提交
97 98 99 100
      pTree->pNode[parentId] = kLeaf;
      return;
    }

H
Haojun Liao 已提交
101
    int32_t ret = pTree->comparFn(pCur, &kLeaf, pTree->param);
H
hzcheng 已提交
102
    if (ret < 0) {
103
      STreeNode t = pTree->pNode[parentId];
H
hzcheng 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116
      pTree->pNode[parentId] = kLeaf;
      kLeaf = t;
    }

    parentId = parentId >> 1;
  }

  if (memcmp(&kLeaf, &pTree->pNode[1], sizeof(kLeaf)) != 0) {
    // winner cannot be identical to the loser, which is pTreeNode[1]
    pTree->pNode[0] = kLeaf;
  }
}

117 118
void tMergeTreeRebuild(SMultiwayMergeTreeInfo* pTree) {
  assert((pTree->totalSources & 0x1) == 0);
H
hzcheng 已提交
119

120 121 122
  tMergeTreeInit(pTree);
  for (int32_t i = pTree->totalSources - 1; i >= pTree->numOfSources; i--) {
    tMergeTreeAdjust(pTree, i);
H
hzcheng 已提交
123 124
  }
}
125 126 127 128 129 130 131 132 133 134 135 136

/*
 * display whole loser tree on screen for debug purpose only.
 */
void tMergeTreePrint(const SMultiwayMergeTreeInfo* pTree) {
  printf("the value of loser tree:\t");
  for (int32_t i = 0; i < pTree->totalSources; ++i) {
    printf("%d\t", pTree->pNode[i].index);
  }

  printf("\n");
}