グローバル関数 ローカル関数
RBAGprintTree
mssCalAggVal
mssClearAggVal
mssFreeAggDat
mssInitAggDat
mssPreAgg
mssReadWriteAgg
mssSetAggVal
mssWriteAggFld
RBAGaddExternalNodes
RBAGcpKey
RBAGcpKeyMemCnt
RBAGdeleteNode
RBAGdetermineAB
RBAGdouble_rotate
RBAGfindMax
RBAGfind_brother
RBAGfree
RBAGfreeAllNode
RBAGfreeKey
RBAGfreeNode
RBAGhasLeftNode
RBAGinit
RBAGinsert
RBAGisExternalNode
RBAGisLeftNode
RBAGisRedNode
RBAGisTopNode
RBAGmakeNode
RBAGmember
RBAGpop
RBAGptree
RBAGrebalanceOnDelete
RBAGrebalanceOnInsert
RBAGsingleRotate
RBAGupdate
RBAGwriteAllNode
RBAGwriteNode
aggAvg
aggAvg2
aggCnt
aggMax
aggMin
aggSum
aggVar
chgAggType
getAggValCnt
getAggValMem
getFname
keyCmp
mergeRBAG
readRBAGkey
setAggType
setFirstLineRBAG
sortAG
0001: /**
0002: * # CHAPTER #
0003: * ============================================================================
0004: * MUSASHIで用いられる集計関連の関数
0005: * ============================================================================
0006: */
0007: #include <mssBase.h>
0008: #include <mssAgg.h>
0009: #include <mssValue.h>
0010: #include <mssOption.h>
0011: #include <mssInput.h>
0012: #include <mssOutput.h>
0013:
0014: #include <stdio.h>
0015: #include <stdlib.h>
0016: #include <string.h>
0017: #include <unistd.h>
0018: #include <signal.h>
0019:
0020: static MssValue *getAggValMem(enum MssAggType aggType, int fc);
0021:
0022: /**
0023: * グローバル変数
0024: */
0025: extern struct mssGlobalVariables mssGV;
0026:
0027: static MssOptKEY *OptKey; /*-kパラメータ*/
0028: static MssOptFLD *OptFld; /*-fパラメータ*/
0029: static int FldCnt; /*集計する項目数*/
0030: static enum MssAggType AGGType; /*集計方法("sum","avg",...)*/
0031: static char fname[MssFileNameMaxLen]; /*一時ファイル名*/
0032: static char readEnd[2]={0xff,0}; /*番兵*/
0033:
0034: /**
0035: * # SECTION #
0036: * ----------------------------------------------------------------------------
0037: * 赤黒木(Red Black Tree)
0038: * ----------------------------------------------------------------------------
0039: * 参考文献: 渡部敏正『データ構造とアルゴリズム』共立出版,2000,6章4節.
0040: * p.224 下から9行目は誤り!!
0041: * 誤) if (v == NULL ) return(1) -> 正) if (v == NULL ) return(0)
0042: */
0043:
0044: /**
0045: * # FUNCTION #
0046: */
0047: static int RBAGhasLeftNode(struct RBAGnode *v)
0048: {
0049: if(v->left->rank !=0){
0050: return(1);
0051: }
0052: return(0);
0053: }
0054:
0055: /**
0056: * # FUNCTION #
0057: */
0058: static int RBAGisExternalNode(struct RBAGnode *v)
0059: {
0060: if(v->rank==0)
0061: return(1);
0062: return(0);
0063: }
0064:
0065: /**
0066: * # FUNCTION #
0067: */
0068: static int RBAGisTopNode(struct RBAGnode *v)
0069: {
0070: if(v->parent->rank==0){
0071: return(1);
0072: }
0073: return(0);
0074: }
0075:
0076: /**
0077: * # FUNCTION #
0078: */
0079: static int RBAGisLeftNode(struct RBAGnode *v)
0080: {
0081: if(v==v->parent->left)
0082: return(1);
0083: return(0);
0084: }
0085:
0086: /**
0087: * # FUNCTION #
0088: */
0089: static int RBAGisRedNode(struct RBAGnode *v)
0090: {
0091: if(v==NULL) return(0);
0092: if(v->rank == v->parent->rank)
0093: return(1);
0094: return(0);
0095: }
0096:
0097: /**
0098: * # FUNCTION #
0099: */
0100: static struct RBAGnode *RBAGfindMax(struct RBAGnode *v)
0101: {
0102: while(!RBAGisExternalNode(v->right))
0103: v=v->right;
0104: return(v);
0105: }
0106:
0107: /**
0108: * # FUNCTION #
0109: */
0110: static struct RBAGnode *RBAGfind_brother(struct RBAGnode *v)
0111: {
0112: if(RBAGisLeftNode(v))
0113: return(v->parent->right);
0114: return(v->parent->left);
0115: }
0116:
0117: /**
0118: * # FUNCTION #
0119: */
0120: static struct RBAGnode *RBAGmakeNode(void)
0121: {
0122: struct RBAGnode *new;
0123: struct RBAGkey *key;
0124: new=(struct RBAGnode *)mssMalloc(sizeof(struct RBAGnode),"RBAGmkNode");
0125: key=(struct RBAGkey *)mssMalloc(sizeof(struct RBAGkey) ,"RBAGmkNode");
0126: new->key=key;
0127: /*new->key.str[0]='\0';*/
0128: new->key->str=NULL;
0129: new->rank = 0;
0130: new->left=new->right=NULL;
0131: return new;
0132: }
0133:
0134: /**
0135: * # FUNCTION #
0136: */
0137: static void RBAGfreeKey(struct RBAGkey *key)
0138: {
0139: mssFree(key->str);
0140: mssFree(key->fld);
0141: mssFree(key->val);
0142: mssFree(key->bkt);
0143: mssFree(key);
0144: }
0145:
0146: /**
0147: * # FUNCTION #
0148: */
0149: static void RBAGfreeNode(struct RBAGnode *v)
0150: {
0151: if(RBAGisExternalNode(v)){
0152: mssFree(v->key);
0153: mssFree(v);
0154: return;
0155: }else{
0156: RBAGfreeKey(v->key);
0157: mssFree(v);
0158: return;
0159: }
0160: }
0161:
0162: /**
0163: * # FUNCTION #
0164: */
0165: static void RBAGfreeAllNode(struct RBAGnode *v)
0166: {
0167: if(RBAGisExternalNode(v)){
0168: mssFree(v->key);
0169: mssFree(v);
0170: return;
0171: }else{
0172: RBAGfreeAllNode(v->left);
0173: RBAGfreeAllNode(v->right);
0174: RBAGfreeNode(v);
0175: return;
0176: }
0177: }
0178:
0179: /**
0180: * # FUNCTION #
0181: */
0182: static int keyCmp(struct mssFldRec *fr, struct RBAGnode *v)
0183: {
0184: int i;
0185: int cmp;
0186:
0187: for(i=0; i<OptKey->flds->cnt; i++){
0188: if( 0 != ( cmp=strcmp( *(fr->pnt+MssFlds2num(OptKey->flds,i)),
0189: *(v->key->fld+MssFlds2num(OptKey->flds,i)) )) ){
0190: return(cmp);
0191: }
0192: }
0193: return(0); /*同じキー!!*/
0194: }
0195:
0196: /**
0197: * # FUNCTION #
0198: */
0199: static struct RBAGnode *RBAGmember(struct mssFldRec *fr, struct RBAGnode *v)
0200: {
0201: struct RBAGnode *vv;
0202:
0203: if(RBAGisExternalNode(v)) return(v);
0204:
0205: if( 0 > keyCmp(fr, v) ){
0206: vv=RBAGmember(fr,v->left);
0207: }else if( 0 < keyCmp(fr, v) ){
0208: vv=RBAGmember(fr,v->right);
0209: }else{
0210: return(v);
0211: }
0212: return(vv);
0213: }
0214:
0215: /**
0216: * # FUNCTION #
0217: */
0218: static void RBAGaddExternalNodes(struct RBAGnode *n)
0219: {
0220: n->left = RBAGmakeNode();
0221: n->right= RBAGmakeNode();
0222: n->left->parent =n;
0223: n->right->parent=n;
0224: }
0225:
0226: /**
0227: * # FUNCTION #
0228: */
0229: static void RBAGsingleRotate(struct RBAGnode *v)
0230: {
0231: struct RBAGnode *p, *pp,*ppp;
0232:
0233: p =v->parent;
0234: pp =p->parent;
0235: ppp=pp->parent;
0236:
0237: if(RBAGisLeftNode(pp)){
0238: ppp->left=p;
0239: }else{
0240: ppp->right=p;
0241: }
0242: if(RBAGisLeftNode(v)){
0243: pp->left=p->right;
0244: pp->left->parent=pp;
0245: p->right=pp;
0246: pp->parent=p;
0247: }else{
0248: pp->right = p->left;
0249: pp->right->parent = pp;
0250: p->left = pp;
0251: pp->parent = p;
0252: }
0253: p->parent=ppp;
0254: }
0255:
0256: /**
0257: * # FUNCTION #
0258: */
0259: static void RBAGdouble_rotate(struct RBAGnode *v)
0260: {
0261: struct RBAGnode *p;
0262: p=v->parent;
0263: if(RBAGisLeftNode(v)){
0264: RBAGsingleRotate(v->left);
0265: RBAGsingleRotate(p);
0266: }else{
0267: RBAGsingleRotate(v->right);
0268: RBAGsingleRotate(p);
0269: }
0270: }
0271:
0272: /**
0273: * # FUNCTION #
0274: */
0275: static void RBAGrebalanceOnInsert(struct RBAGnode *v)
0276: {
0277: struct RBAGnode *w, *p, *pp;
0278: int p_is_left;
0279:
0280: p=v->parent;
0281: pp=p->parent;
0282: if(RBAGisTopNode(p)){
0283: return;
0284: }
0285: if(RBAGisRedNode(p)){
0286: p_is_left=0;
0287: if((p_is_left=RBAGisLeftNode(p))){
0288: w=pp->right;
0289: }else{
0290: w=pp->left;
0291: }
0292: if(RBAGisRedNode(w)){
0293: (pp->rank)++;
0294: if(!RBAGisTopNode(pp) && RBAGisRedNode(pp->parent)){
0295: RBAGrebalanceOnInsert(pp);
0296: }
0297: }else{
0298: if(RBAGisLeftNode(v)){
0299: if(p_is_left){
0300: RBAGsingleRotate(v);
0301: }else{
0302: RBAGdouble_rotate(v);
0303: }
0304: }else{
0305: if(p_is_left){
0306: RBAGdouble_rotate(v);
0307: }else{
0308: RBAGsingleRotate(v);
0309: }
0310: }
0311: }
0312: }
0313: }
0314:
0315: /**
0316: * # FUNCTION #
0317: */
0318: static void RBAGdetermineAB(struct RBAGnode **a, struct RBAGnode **b, struct RBAGnode *v, struct RBAGnode *u)
0319: {
0320: if(RBAGisLeftNode(v)){
0321: *a=u->right;
0322: *b=u->left;
0323: }else{
0324: *a=u->left;
0325: *b=u->right;
0326: }
0327: }
0328:
0329: /**
0330: * # FUNCTION #
0331: */
0332: static void RBAGrebalanceOnDelete(struct RBAGnode *v)
0333: {
0334: struct RBAGnode *p,*u,*a,*b;
0335: int v_is_left, p_was_red;
0336:
0337: p=v->parent;
0338: if(v->rank+1 >= p->rank)
0339: return;
0340: u=RBAGfind_brother(v);
0341: RBAGdetermineAB(&a,&b,v,u);
0342: v_is_left=RBAGisLeftNode(v);
0343: p_was_red=RBAGisRedNode(p);
0344: if(RBAGisRedNode(u)){
0345: if(RBAGisRedNode(a) || RBAGisRedNode(b))
0346: return;
0347: RBAGsingleRotate(a);
0348: RBAGrebalanceOnDelete(v);
0349: }else{
0350: if(!RBAGisRedNode(a)){
0351: if(!RBAGisRedNode(b)){
0352: (p->rank)--;
0353: if(!p_was_red)
0354: RBAGrebalanceOnDelete(p);
0355: }else{
0356: RBAGdouble_rotate(b);
0357: (b->rank)++;
0358: (p->rank)--;
0359: }
0360: }else{
0361: RBAGsingleRotate(a);
0362: (u->rank)++;
0363: (u->rank)--;
0364: }
0365: }
0366: }
0367:
0368:
0369: /**
0370: * # FUNCTION #
0371: */
0372: static void RBAGptree(struct RBAGnode *p,int h)
0373: {
0374: int i,j;
0375:
0376: if(!RBAGisExternalNode(p)){
0377: RBAGptree(p->left, h+1);
0378: if(0 == strcmp(p->key->str,readEnd) ){
0379: for(i=1; i<=h; i++) fprintf(stderr," ");
0380: printf("key='EOF' ");
0381: /*printf(" bktCnt=%d bkt=",p->key->bktCnt);*/
0382: for(j=0; j<PWayA; j++){
0383: if(*(p->key->bkt+j) == 1)
0384: printf("%d ",j);
0385: }
0386: printf("\n");
0387: }else{
0388: for(i=0; i<h; i++) printf(" ");
0389: printf("key='");
0390: for(j=0; j<OptKey->flds->cnt; j++){
0391: printf("%s ",*(p->key->fld+MssFlds2num(OptKey->flds,j)));
0392: }
0393: printf("' fld=");
0394: for(j=0; j<OptFld->flds->cnt; j++){
0395: printf("%g ",(p->key->val+j)->v.d);
0396: }
0397:
0398: /*printf(" bktCnt=%d bkt=",p->key->bktCnt);*/
0399: for(j=0; j<PWayA; j++){
0400: if(*(p->key->bkt+j) == 1)
0401: printf("%d ",j);
0402: }
0403: /*for(j=0; j<p->key->bktCnt; j++){*/
0404: /* printf("%d ",*(p->key->bkt+j));*/
0405: /*}*/
0406: printf("\n");
0407: }
0408: RBAGptree(p->right,h+1);
0409: }
0410: }
0411:
0412: /**
0413: * # FUNCTION #
0414: * RBAGcpKeyの関数で確保されたメモリ量の計算
0415: */
0416: static int RBAGcpKeyMemCnt(struct mssFldRec *fr)
0417: {
0418:
0419: int memCnt=0;
0420:
0421: if(fr->eof==1){ /*EOF*/
0422: /*文字列として番兵を入れておく*/
0423: memCnt+=2*sizeof(char);
0424:
0425: /*キー項目のアドレスを全て番兵に設定する*/
0426: memCnt+=FldCnt*sizeof(char *);
0427:
0428: /*sortAGでは以下のbkt変数は利用していない。mergeRBAGで利用。*/
0429: memCnt+=(sizeof(int)*PWayA);
0430:
0431: /*ダミーで作っておく(freeのため)*/
0432: memCnt+=(sizeof(MssValue));
0433:
0434: }else{
0435:
0436: /*frの全項目をまるごとコピー*/
0437: memCnt+=fr->chrCnt*sizeof(char);
0438:
0439: /*キー項目のアドレスを計算によりセット*/
0440: memCnt+=FldCnt*sizeof(char *);
0441:
0442: switch(AGGType){
0443: case aggSUM:
0444: case aggCNT:
0445: case aggMIN:
0446: case aggMAX:
0447: memCnt=sizeof(MssValue)*(OptFld->flds->cnt)*1;
0448: break;
0449: case aggAVG:
0450: case aggAVG2:
0451: memCnt=sizeof(MssValue)*(OptFld->flds->cnt)*2;
0452: break;
0453: case aggSTD:
0454: case aggSTDP:
0455: case aggVAR:
0456: case aggVARP:
0457: memCnt=sizeof(MssValue)*(OptFld->flds->cnt)*3;
0458: break;
0459: }
0460:
0461: /*sortAGでは以下のbkt変数は利用していない。mergeRBAGで利用。*/
0462: memCnt+=(sizeof(int)*PWayA);
0463: }
0464: return(memCnt);
0465: }
0466:
0467: /**
0468: * # FUNCTION #
0469: */
0470: static void RBAGcpKey(struct RBAGnode *v, struct mssFldRec *fr, int bkt, MssValue *val)
0471: {
0472:
0473: int i;
0474:
0475: if(fr->eof==1){ /*EOF*/
0476: /*文字列として番兵を入れておく*/
0477: v->key->str = mssMalloc(2*sizeof(char),"RBAGAGtree1");
0478: memcpy(v->key->str, readEnd, 2);
0479:
0480: /*キー項目のアドレスを全て番兵に設定する*/
0481: v->key->fld = mssMalloc(FldCnt*sizeof(char *),"RBAGAGtree2");
0482: for(i=0; i<FldCnt; i++){
0483: *(v->key->fld+i) = v->key->str;
0484: }
0485:
0486: /*sortAGでは以下のbkt変数は利用していない。mergeRBAGで利用。*/
0487: v->key->bkt = mssCalloc(sizeof(int)*PWayA, "RBAGtree");
0488: *(v->key->bkt+bkt) = 1;
0489: /**v->key->bkt = bkt;*/
0490: /*v->key->bktCnt = 1;*/
0491:
0492: /*ダミーで作っておく(freeのため)*/
0493: v->key->val = mssMalloc(sizeof(MssValue),"RBAGAGtree3");
0494:
0495: }else{
0496:
0497: /*frの全項目をまるごとコピー*/
0498: v->key->str = mssMalloc(fr->chrCnt*sizeof(char),"RBAGAGtree4");
0499: memcpy(v->key->str, *fr->pnt, fr->chrCnt);
0500:
0501: /*キー項目のアドレスを計算によりセット*/
0502: v->key->fld = mssMalloc(FldCnt*sizeof(char *),"RBAGAGtree5");
0503: for(i=0; i<FldCnt; i++){
0504: *(v->key->fld+i) = v->key->str + (*(fr->pnt+i) - *fr->pnt);
0505: }
0506:
0507: /*集計値領域の確保*/
0508: v->key->val=getAggValMem(AGGType, OptFld->flds->cnt);
0509:
0510: /*集計値の計算*/
0511: mssCalAggVal(v->key->val, AGGType, val);
0512:
0513: /*sortAGでは以下のbkt変数は利用していない。mergeRBAGで利用。*/
0514: v->key->bkt = mssCalloc(sizeof(int)*PWayA, "RBAGtree");
0515: *(v->key->bkt+bkt) = 1;
0516: }
0517: }
0518:
0519: /**
0520: * # FUNCTION #
0521: * 指定のノードをFldRec構造体のデータで更新
0522: */
0523: static void RBAGupdate(struct RBAGnode *v, struct mssFldRec *fr, int bkt, MssValue *val)
0524: {
0525: /*更新したバケット番号をバケットフラグに更新する*/
0526: *(v->key->bkt+bkt) = 1;
0527:
0528: if(fr->eof!=1){ /*not EOF*/
0529: /*集計値の計算*/
0530: mssCalAggVal(v->key->val, AGGType, val);
0531: }
0532: }
0533:
0534: /**
0535: * # FUNCTION #
0536: * RBtreeにFldRec構造体のデータを追加
0537: * 既にキーが存在すればRBAGupdateで値を更新
0538: */
0539: static int RBAGinsert(struct RBAGnode *v, struct mssFldRec *fr, int bkt, MssValue *val)
0540: {
0541: int memCnt=0;
0542:
0543: v = RBAGmember(fr, v);
0544:
0545: /*キーが存在しなければ追加*/
0546: if(RBAGisExternalNode(v)){
0547: RBAGcpKey(v, fr, bkt, val);
0548: memCnt=RBAGcpKeyMemCnt(fr);
0549: v->rank=1;
0550: RBAGaddExternalNodes(v);
0551: RBAGrebalanceOnInsert(v);
0552: memCnt+=sizeof(struct RBAGnode)*2;
0553: memCnt+=sizeof(struct RBAGkey )*2;
0554:
0555: /*キーが存在すれば更新*/
0556: }else{
0557: RBAGupdate(v, fr, bkt,val);
0558: }
0559:
0560: return(memCnt);
0561: }
0562:
0563:
0564: /**
0565: * # FUNCTION #
0566: * 指定のノードを削除
0567: */
0568: static void RBAGdeleteNode(struct RBAGnode *v)
0569: {
0570: struct RBAGnode *w,*x;
0571:
0572: if(RBAGisExternalNode(v)){
0573: fprintf(stderr,"Not found such node\n");
0574: return;
0575: }
0576: if(RBAGhasLeftNode(v)){
0577: w=RBAGfindMax(v->left);
0578: if(w->parent != v){
0579: w->parent->right = w->left;
0580: w->left->parent = w->parent;
0581: }
0582: x=w->left;
0583: RBAGfreeNode(w->right);
0584: /*free(w->right->key);*/
0585: /*free(w->right);*/
0586:
0587: if(RBAGisLeftNode(v)){
0588: v->parent->left=w;
0589: }else{
0590: v->parent->right=w;
0591: }
0592: if(w->parent != v){
0593: w->left = v->left;
0594: w->left->parent = w;
0595: }
0596: w->rank = v->rank;
0597: w->parent = v->parent;
0598: w->right = v->right;
0599: w->right->parent=w;
0600: RBAGfreeNode(v);
0601: /*free(v->key);*/
0602: /*free(v);*/
0603: }else{
0604: w=v->right;
0605: if(RBAGisLeftNode(v)){
0606: v->parent->left=w;
0607: }else{
0608: v->parent->right=w;
0609: }
0610: w->parent=v->parent;
0611: RBAGfreeNode(v->left);
0612: RBAGfreeNode(v);
0613: /*free(v->left->key);*/
0614: /*free(v->left);*/
0615: /*free(v->key);*/
0616: /*free(v);*/
0617: x=w;
0618: }
0619:
0620: RBAGrebalanceOnDelete(x);
0621: }
0622:
0623: /**
0624: * # FUNCTION #
0625: * RBtreeから優先行のノードアドレスを返す
0626: * この処理でノードを削除はしない。呼び出す本体側でRBAGdeleteNode(node)を実行
0627: */
0628: static struct RBAGnode *RBAGpop(struct RBAGnode *v)
0629: {
0630: struct RBAGnode *vv;
0631:
0632: if(RBAGisExternalNode(v)){
0633: return(NULL);
0634: }else{
0635: vv=v;
0636: while(!RBAGisExternalNode(vv)){
0637: vv=vv->left; /*rightを辿れば最大、leftは最小*/
0638: }
0639: return(vv->parent);
0640: }
0641: }
0642:
0643: /**
0644: * # FUNCTION #
0645: * RBtreeをツリーとして書き出す(デバッグ用)
0646: */
0647: void RBAGprintTree(char *s,struct RBAGnode *pp)
0648: {
0649: printf("%s\n",s);
0650: RBAGptree(pp,0);
0651: }
0652:
0653: /**
0654: * # FUNCTION #
0655: * 指定のノードを行として書き出す
0656: */
0657: static void RBAGwriteNode(struct RBAGnode *p, int valCnt, struct mssFPW *fpw, FILE *valFile)
0658: {
0659: int i;
0660:
0661: /*データテキストの出力*/
0662: for(i=0; i<FldCnt-1; i++){
0663: mssWriteStr(*(p->key->fld+i),fpw); mssWriteDlm(fpw);
0664: }
0665: mssWriteStr(*(p->key->fld+i),fpw); mssWriteRet(fpw);
0666:
0667: fwrite(p->key->val,sizeof(MssValue),valCnt,valFile);
0668: }
0669:
0670: /**
0671: * # FUNCTION #
0672: * RBtreeを全て行として書き出す
0673: */
0674: static void RBAGwriteAllNode(struct RBAGnode *p, int valCnt, struct mssFPW *fpw, FILE *valFile)
0675: {
0676:
0677: if(!RBAGisExternalNode(p)){
0678: RBAGwriteAllNode(p->left,valCnt,fpw,valFile);
0679: RBAGwriteNode(p,valCnt,fpw,valFile);
0680: RBAGwriteAllNode(p->right,valCnt,fpw,valFile);
0681: }
0682: }
0683:
0684: /**
0685: * # FUNCTION #
0686: * RBtreeのメモリ領域解放
0687: */
0688: static void RBAGfree(struct RBAGnode *v)
0689: {
0690:
0691: RBAGfreeAllNode(v->left);
0692: mssFree(v->key);
0693: mssFree(v);
0694: }
0695:
0696: /**
0697: * # FUNCTION #
0698: * RBnodeの初期化(ノード作成)
0699: */
0700: static struct RBAGnode *RBAGinit(struct RBAGnode *rb)
0701: {
0702: /*赤黒木の初期化*/
0703: rb = RBAGmakeNode();
0704: rb->parent = rb;
0705: rb->right = NULL;
0706: rb->rank = 0;
0707: rb->left = RBAGmakeNode();
0708: rb->left->parent = rb;
0709: return(rb);
0710: }
0711:
0712: /**
0713: * # SECTION #
0714: * ----------------------------------------------------------------------------
0715: * 集計タイプ別の演算
0716: * ----------------------------------------------------------------------------
0717: */
0718:
0719: /**
0720: * # FUNCTION #
0721: * 合計集計
0722: */
0723: static void aggSum(MssValue *val, MssValue *val2)
0724: {
0725: int i;
0726: for(i=0; i<OptFld->flds->cnt; i++){
0727: *(val+i)=mssVadd(*(val+i), *(val2+i));
0728: }
0729: }
0730:
0731: /**
0732: * # FUNCTION #
0733: * 件数集計
0734: */
0735: static void aggCnt(MssValue *val, MssValue *val2)
0736: {
0737: int i;
0738:
0739: for(i=0; i<OptFld->flds->cnt; i++){
0740: if((val2+i)->nul!=1){
0741: *(val+i)=mssVcntUp(*(val+i));
0742: }
0743: }
0744: }
0745:
0746: /**
0747: * # FUNCTION #
0748: * 平均集計
0749: */
0750: static void aggAvg(MssValue *val, MssValue *val2)
0751: {
0752: int i;
0753: for(i=0; i<OptFld->flds->cnt; i++){
0754: *(val+i)=mssVadd(*(val+i), *(val2+i));
0755: if((val2+i)->nul!=1){
0756: *(val+OptFld->flds->cnt+i)=mssVcntUp(*(val+OptFld->flds->cnt+i));
0757: }
0758: }
0759: }
0760:
0761: /**
0762: * # FUNCTION #
0763: * 平均集計2
0764: */
0765: static void aggAvg2(MssValue *val, MssValue *val2)
0766: {
0767: int i;
0768: for(i=0; i<OptFld->flds->cnt; i++){
0769: *(val+i)=mssVadd(*(val+i), *(val2+i));
0770: *(val+OptFld->flds->cnt+i)=mssVadd(*(val+OptFld->flds->cnt+i), *(val2+OptFld->flds->cnt+i));
0771: }
0772: }
0773:
0774: /**
0775: * # FUNCTION #
0776: * 最小値集計
0777: */
0778: static void aggMin(MssValue *val, MssValue *val2)
0779: {
0780: int i;
0781: for(i=0; i<OptFld->flds->cnt; i++){
0782: *(val+i)=mssVmin(*(val+i), *(val2+i));
0783: }
0784: }
0785:
0786: /**
0787: * # FUNCTION #
0788: * 最大値集計
0789: */
0790: static void aggMax(MssValue *val, MssValue *val2)
0791: {
0792: int i;
0793: for(i=0; i<OptFld->flds->cnt; i++){
0794: *(val+i)=mssVmax(*(val+i), *(val2+i));
0795: }
0796: }
0797:
0798: /**
0799: * # FUNCTION #
0800: * 分散集計
0801: */
0802: static void aggVar(MssValue *val, MssValue *x)
0803: {
0804: int i;
0805: MssValue *n;
0806: MssValue *s1;
0807: MssValue *s2;
0808: MssValue const1;
0809:
0810: mssVinit(&const1,DBL);
0811: const1.v.d=1;
0812:
0813: /*x :仮平均との差(x)*/
0814: /*n :個数(n)*/
0815: /*s1:平均(s1)*/
0816: /*s2:平方和(s2)*/
0817: n =val;
0818: s1=val+OptFld->flds->cnt;
0819: s2=val+OptFld->flds->cnt*2;
0820: for(i=0; i<OptFld->flds->cnt; i++){
0821: if((x+i)->nul!=1){
0822: *(n+i)=mssVcntUp(*(n+i));
0823: }
0824: *(x+i)=mssVsub(*(x+i), *(s1+i));
0825: *(s1+i)=mssVadd(*(s1+i), mssVdiv(*(x+i), *(n+i)));
0826: *(s2+i)=mssVadd(
0827: *(s2+i),
0828: mssVdiv(
0829: mssVmul(
0830: mssVsub( *(n+i), const1),
0831: mssVmul(*(x+i),*(x+i))
0832: ),
0833: *(n+i)
0834: )
0835: );
0836: }
0837: }
0838:
0839: /**
0840: * # FUNCTION #
0841: * 併合時には集計方法が変わるものがある
0842: *ここに具体例を説明すること
0843: */
0844: static enum MssAggType chgAggType(enum MssAggType aggType)
0845: {
0846: switch(aggType){
0847: case aggSUM:
0848: return(aggSUM);
0849: break;
0850: case aggCNT:
0851: return(aggSUM);
0852: break;
0853: case aggMIN:
0854: return(aggMIN);
0855: break;
0856: case aggMAX:
0857: return(aggMAX);
0858: break;
0859: case aggAVG:
0860: return(aggAVG2);
0861: break;
0862: case aggSTD:
0863: case aggSTDP: /*ありえないが警告を避けるため*/
0864: return(aggSTD);
0865: break;
0866: case aggVAR:
0867: case aggVARP: /*ありえないが警告を避けるため*/
0868: return(aggVAR);
0869: break;
0870: case aggAVG2: /*コンパイル警告を防ぐために*/
0871: return(aggAVG2);
0872: break;
0873: }
0874: return(aggType);
0875: }
0876:
0877:
0878: /**
0879: * # SECTION #
0880: * ----------------------------------------------------------------------------
0881: * 集計関連関数
0882: * ----------------------------------------------------------------------------
0883: */
0884:
0885: /**
0886: * # FUNCTION #
0887: * 一時ファイル名の取得
0888: */
0889: static char *getFname(char *prefix, int number)
0890: {
0891: /*fnameはグローバル変数*/
0892: sprintf(fname,"%s%d",prefix,number);
0893: return(fname);
0894: }
0895:
0896: /**
0897: * # FUNCTION #
0898: * mssFldRec構造体に一行読み込む(番兵処理)
0899: */
0900: static void readRBAGkey( struct mssFPR *fp, struct mssFldRec *fr)
0901: {
0902: int i;
0903:
0904: if(EOF==mssReadFldRec(fp,fr)){
0905: for(i=0; i<fr->fldCnt; i++)
0906: *(fr->pnt+i)=readEnd; /*EOFの時は番兵を入れる*/
0907: }
0908: }
0909:
0910: /**
0911: * # FUNCTION #
0912: * 各バケットの最初の行をRBキューに読み込み
0913: * mergeRB,preSortから呼び出される
0914: * iFromからiToまでのファイルの先頭行をRBキューに入れる
0915: * ad : iFile,rbをセットする
0916: * iFrom: 開始ファイル番号
0917: * iTo : 終了ファイル番号
0918: */
0919: static void setFirstLineRBAG(struct mssAggDat *ad, int iFrom, int iTo)
0920: {
0921: int bkt; /*現在処理中のバケット番号(0から始まる)*/
0922: int i;
0923:
0924: /*ad->bktCnt=iTo-iFrom+1; バケット数の設定*/
0925:
0926: /*プライオリティキューの初期化*/
0927: ad->rb=RBAGinit(ad->rb);
0928: bkt=0;
0929: for(i=iFrom; i<=iTo; i++){
0930: ad->fr[bkt]=mssInitFldRec(FldCnt);
0931:
0932: ad->iFile[bkt]=mssOpenFPR(getFname(ad->prefixTxt,i),4);
0933: ad->vFile[bkt]=fopen(getFname(ad->prefixVal,i),"rb");
0934:
0935: /*一行(先頭行)読み込み*/
0936: readRBAGkey(ad->iFile[bkt],ad->fr[bkt]);
0937: fread(ad->val, sizeof(MssValue), ad->valCnt, ad->vFile[bkt]);
0938:
0939: /*赤黒木に挿入(物理的にコピー)*/
0940: RBAGinsert(ad->rb->left,ad->fr[bkt],bkt, ad->val);
0941: bkt++;
0942: }
0943: }
0944:
0945: /**
0946: * # FUNCTION #
0947: *RBキューを用いたPWayマージ
0948: * 既に並べ変わっているバケット(iCnt個)を併合していく
0949: * 最後の一つになるまで併合はしない
0950: * PWayA個より少なくなったときに併合を止める
0951: */
0952: static void mergeRBAG(struct mssAggDat *ad)
0953: {
0954: int bkt[PWayA]; /*Pway併合時にRBtreeからpopしたデータのバケットNo*/
0955: int bktCnt; /*そのバケット数*/
0956: struct RBAGnode *node; /*popにて取りだしたノードを格納*/
0957:
0958: struct mssFPW *oFile; /*出力ワークファイルポインタ*/
0959: FILE *vFile; /*出力ワークファイルポインタ*/
0960:
0961: int iStart; /*入力ワークファイルの開始番号(ファイル名の一部)*/
0962: int iEnd; /*入力ワークファイルの終了番号(ファイル名の一部)*/
0963: int oStart; /*出力ワークファイルの開始番号(ファイル名の一部)*/
0964: int oEnd; /*出力ワークファイルの終了番号(ファイル名の一部)*/
0965: int iFrom,iTo; /*併合する時のファイル番号*/
0966: int k;
0967: int i;
0968:
0969: /*次のループでin,outをswapするので、ここでは逆に定義*/
0970: iStart=ad->iEnd+1;
0971: iEnd =ad->iEnd+1;
0972: oStart=ad->iStart;
0973: oEnd =ad->iEnd;
0974:
0975: /*ファイルを併合するループ iCntがPWayA個より大きい場合まわり続ける*/
0976: while(1){
0977: mssSwapInt(&iStart,&oStart);
0978: mssSwapInt(&iEnd ,&oEnd );
0979: oEnd=oStart;
0980:
0981: /*入力ファイル数がPWayA以下ならば終了*/
0982: if(iEnd-iStart+1 <= PWayA){
0983: ad->iStart = iStart;
0984: ad->iEnd = iEnd;
0985: break;
0986: }
0987:
0988: /*Pway個のiFileを一つのoFileに書き出す"を繰り返すループ*/
0989: k=0;
0990: while(1){
0991: /*各バケットの最初行をキューに入れる*/
0992: iFrom= k *PWayA+iStart; /*PWayA=3で一時ファイルが0,1,2,3,4,5,6の時*/
0993: iTo =(k+1)*PWayA+iStart-1; /* iFrom: 0 3 6*/
0994: if(iTo>iEnd) iTo=iEnd; /* iTo : 2 5 6*/
0995: setFirstLineRBAG(ad, iFrom,iTo);
0996:
0997: /*出力ファイルオープン*/
0998: oFile=mssOpenFPW(getFname(ad->prefixTxt,oEnd),0,0);
0999: vFile=fopen(getFname(ad->prefixVal,oEnd),"wb");
1000:
1001: /*各バケットから一行づつ読み込み書き出すループ*/
1002: while(1) {
1003: node=RBAGpop(ad->rb->left); /*キューから一行取り出し*/
1004: if(strcmp(node->key->str,readEnd)==0)/*readEnd(番兵)を取り出したら終了*/
1005: break;
1006: RBAGwriteNode(node,ad->valCnt,oFile,vFile); /*一行書き出し*/
1007: bktCnt=0; /*popで取り出したkey値のバケット数*/
1008: for(i=0; i<PWayA; i++){
1009: if(*(node->key->bkt+i) == 1)
1010: bkt[bktCnt++]=i; /*バケット番号をセット*/
1011: }
1012: RBAGdeleteNode(node); /*取り出したノードの削除*/
1013:
1014: /*popしたバケットから新に読みこんでRBtreeに挿入する*/
1015: for(i=0; i<bktCnt; i++){
1016: readRBAGkey(ad->iFile[bkt[i]],ad->fr[bkt[i]]);
1017: fread(ad->val,sizeof(MssValue),ad->valCnt,ad->vFile[bkt[i]]);
1018: RBAGinsert(ad->rb->left,ad->fr[bkt[i]],bkt[i],ad->val);
1019: }
1020: }
1021: RBAGfree(ad->rb); /*キューの開放*/
1022: for(i=0; i<=iTo-iFrom; i++){ /*入力ファイルのクローズ*/
1023: mssCloseFPR(ad->iFile[i]);
1024: fclose(ad->vFile[i]);
1025: mssFreeFldRec(ad->fr[i]);
1026: }
1027: mssCloseFPW(oFile); /*出力ファイルのクローズ*/
1028: fclose(vFile); /*出力ファイルのクローズ*/
1029: if(iTo==iEnd)break; /*最後のバケットまでいけば終了*/
1030: oEnd++; /*出力ファイル番号カウントアップ*/
1031: k++; /*併合回数カウントアップ*/
1032: }
1033: for(i=iStart; i<=iEnd; i++){
1034: unlink(getFname(ad->prefixTxt,i)); /*入力ワークファイルの削除*/
1035: unlink(getFname(ad->prefixVal,i)); /*入力ワークファイルの削除*/
1036: }
1037: }
1038: }
1039:
1040: /**
1041: * # FUNCTION #
1042: *集計しながらsortする関数(uniq,sum,avg,max,min,cnt,stdev,var...)
1043: *集計しながら赤黒木を作成
1044: * メモリ消費がMAXを越えたら一時ファイルに書き出し
1045: */
1046: static void sortAG(struct mssAggDat *ad, struct mssFPR *fpr)
1047: {
1048: struct mssFldRec *fr; /*入力ファイルをキー順に並べ換えるためのバッファ*/
1049: int pid; /*プロセスID(ファイル名の一部)*/
1050: int oNum; /*ワークファイル番号のカウントアップ変数*/
1051: int memCnt; /*メモリ消費量*/
1052:
1053: struct RBAGnode *rb=NULL; /*赤黒木*/
1054: struct mssFPW *outFile; /*出力一時ファイル*/
1055: FILE *valFile; /*出力一時ファイル*/
1056:
1057: fr=mssInitFldRec(FldCnt);/*FldRecの初期化*/
1058: rb=RBAGinit(rb); /*RBAGtreeの初期化*/
1059:
1060: /*ファイル名のプレフィックスの設定*/
1061: pid=getpid();
1062: if(strlen(ad->tmpDir) > MssFileNameMaxLen - 50 ) {
1063: mssShowErrMsg("length of path name must be less than %d",MssFileNameMaxLen-50);
1064: exit(mssErrorNoDefault);
1065: }
1066: sprintf(ad->prefixTxt,"%s/xt##%d-PreAggTxt-",ad->tmpDir,pid);
1067: sprintf(ad->prefixVal,"%s/xt##%d-PreAggVal-",ad->tmpDir,pid);
1068:
1069: memCnt=0; /*消費メモリカウンタのクリア*/
1070: oNum=0; /*出力ファイル番号*/
1071: while(1){
1072: /*データの読み込み*/
1073: mssReadFldRec(fpr,fr);
1074: (*ad->inCnt)++;
1075:
1076: /*赤黒木のサイズがMaxを越えたら もしくは 最終行を検出したら*/
1077: /*ワークファイルへ書き出す*/
1078: if( memCnt >= MaxMemA || fr->eof==1){
1079: outFile=mssOpenFPW(getFname(ad->prefixTxt,oNum),0,0);/*出力ファイルオープン*/
1080: valFile=fopen(getFname(ad->prefixVal,oNum),"wb"); /*出力ファイルオープン*/
1081: RBAGwriteAllNode(rb->left,ad->valCnt, outFile,valFile);/*RBtree全て出力*/
1082: mssCloseFPW(outFile); /*出力ファイルのクローズ*/
1083: fclose(valFile); /*出力ファイルのクローズ*/
1084: oNum++; /*出力ファイル数countUp*/
1085: RBAGfree(rb); /*RBAGtreeの領域解放*/
1086: if(fr->eof==1){ /*最終行で終了*/
1087: (*ad->inCnt)--;
1088: break;
1089: }
1090: rb=RBAGinit(rb); /*RBAGtreeの初期化*/
1091: memCnt=0; /*消費メモリカウンタのクリア*/
1092: }
1093:
1094: /*赤黒木に挿入して(物理的にコピー)、メモリ消費をカウントアップ*/
1095: mssSetAggVal(ad->val, fr->pnt);
1096: memCnt += RBAGinsert(rb->left,fr,1,ad->val);
1097: }
1098: mssFreeFldRec(fr);/*FldRecの初期化*/
1099:
1100: ad->iStart = 0;
1101: ad->iEnd = oNum-1;
1102: }
1103:
1104: /**
1105: * # FUNCTION #
1106: * 文字列としての集計方法("sum","avg","min"..)をenumAGtypeの要素に変換
1107: */
1108: static enum MssAggType setAggType(char *str)
1109: {
1110: if( 0==strcmp("sum",str) ){
1111: return(aggSUM);
1112: }else if( 0==strcmp("avg",str) ){
1113: return(aggAVG);
1114: }else if( 0==strcmp("cnt",str) ){
1115: return(aggCNT);
1116: }else if( 0==strcmp("max",str) ){
1117: return(aggMAX);
1118: }else if( 0==strcmp("min",str) ){
1119: return(aggMIN);
1120: }else if( 0==strcmp("std",str) ){
1121: return(aggSTD);
1122: }else if( 0==strcmp("stdp",str) ){
1123: return(aggSTDP);
1124: }else if( 0==strcmp("var",str) ){
1125: return(aggVAR);
1126: }else if( 0==strcmp("varp",str) ){
1127: return(aggVARP);
1128: }
1129:
1130: mssShowErrMsg("Invalid aggregation method:'%s'",str);
1131: exit(mssErrorNoDefault);
1132:
1133: return(-1); /*コンパイラwarningメッセージを避けるため*/
1134: }
1135:
1136: /**
1137: * # FUNCTION #
1138: * 項目数(fc)と集計タイプに応じて集計値領域で確保するMssValueの数を返す。
1139: */
1140: static int getAggValCnt(enum MssAggType aggType, int fc)
1141: {
1142: switch(aggType){
1143: case aggSUM:
1144: case aggCNT:
1145: case aggMIN:
1146: case aggMAX:
1147: return(fc);
1148: break;
1149: case aggAVG:
1150: case aggAVG2:
1151: return(fc*2);
1152: break;
1153: case aggSTD:
1154: case aggSTDP:
1155: case aggVAR:
1156: case aggVARP:
1157: return(fc*3);
1158: break;
1159: }
1160: return(fc);
1161: }
1162:
1163: /**
1164: * # FUNCTION #
1165: * 項目数(fc)と集計タイプに応じて集計値領域を確保する。
1166: */
1167: static MssValue *getAggValMem(enum MssAggType aggType, int fc)
1168: {
1169: MssValue *val;
1170: switch(aggType){
1171: case aggSUM:
1172: case aggCNT:
1173: case aggMIN:
1174: case aggMAX:
1175: val = mssMalloc(sizeof(MssValue)*fc ,"RBAGAGtree6");
1176: break;
1177: case aggAVG:
1178: case aggAVG2:
1179: val = mssMalloc(sizeof(MssValue)*fc*2,"RBAGAGtree6");
1180: break;
1181: case aggSTD:
1182: case aggSTDP:
1183: case aggVAR:
1184: case aggVARP:
1185: val = mssMalloc(sizeof(MssValue)*fc*3,"RBAGAGtree6");
1186: break;
1187: default:
1188: val = NULL;
1189: }
1190: mssClearAggVal(val, aggType, fc);
1191: return(val);
1192: }
1193:
1194: /**
1195: * # FUNCTION #
1196: * 項目数(fc)と集計タイプに応じて集計値領域(val)をクリアする。
1197: */
1198: void mssClearAggVal(MssValue *val, enum MssAggType aggType, int fc)
1199: {
1200: int i;
1201: switch(aggType){
1202: case aggSUM:
1203: case aggCNT:
1204: for(i=0; i<fc; i++) mssVinit(val+i,DBL);
1205: break;
1206: case aggMIN:
1207: for(i=0; i<fc; i++) {mssVinit(val+i,DBL); mssVclearMax( val+i );}
1208: break;
1209: case aggMAX:
1210: for(i=0; i<fc; i++) {mssVinit(val+i,DBL); mssVclearMin( val+i );}
1211: break;
1212: case aggAVG:
1213: case aggAVG2:
1214: for(i=0; i<fc*2; i++) mssVinit(val+i,DBL);
1215: break;
1216: case aggSTD:
1217: case aggSTDP:
1218: case aggVAR:
1219: case aggVARP:
1220: for(i=0; i<fc*3; i++) mssVinit(val+i,DBL);
1221: break;
1222: }
1223: }
1224:
1225: /**
1226: * # FUNCTION #
1227: * 集計タイプに応じて、集計値(val)を新しい値(val2)によって更新する。
1228: */
1229: void mssCalAggVal(MssValue *val, enum MssAggType aggType, MssValue *val2)
1230: {
1231: /*val2:f=の値 val:計算結果*/
1232: switch(aggType){
1233: case aggSUM:
1234: aggSum( val ,val2);
1235: break;
1236: case aggCNT:
1237: aggCnt( val ,val2);
1238: break;
1239: case aggAVG:
1240: aggAvg( val ,val2);
1241: break;
1242: case aggAVG2:
1243: aggAvg2( val ,val2);
1244: break;
1245: case aggMIN:
1246: aggMin( val ,val2);
1247: break;
1248: case aggMAX:
1249: aggMax( val ,val2);
1250: break;
1251: case aggSTD:
1252: case aggSTDP:
1253: case aggVAR:
1254: case aggVARP:
1255: aggVar( val ,val2);
1256: break;
1257: }
1258: }
1259:
1260: /**
1261: * # FUNCTION #
1262: * 集計タイプに応じて、最終結果を計算し、一行出力する。
1263: */
1264: void mssWriteAggFld( char **fld, MssValue *val, enum MssAggType aggType, struct mssFPW *fpw)
1265: {
1266: MssValue const1;
1267: int i;
1268:
1269: mssVinit(&const1,DBL);
1270: const1.v.d=1;
1271:
1272: switch(aggType){
1273: case aggSUM:
1274: break;
1275: case aggCNT:
1276: break;
1277: case aggMIN:
1278: break;
1279: case aggMAX:
1280: break;
1281: case aggAVG: /*意味無いがコンパイルエラーを避けるため*/
1282: case aggAVG2:
1283: for(i=0; i<OptFld->flds->cnt; i++){
1284: *(val+i)=mssVdiv(*(val+i), *(val+OptFld->flds->cnt+i) );
1285: }
1286: break;
1287: case aggVAR:
1288: for(i=0; i<OptFld->flds->cnt; i++){
1289: *(val+i)=mssVdiv(*(val+OptFld->flds->cnt*2+i), mssVsub(*(val+i),const1) );
1290: }
1291: break;
1292: case aggVARP:
1293: for(i=0; i<OptFld->flds->cnt; i++){
1294: *(val+i)=mssVdiv(*(val+OptFld->flds->cnt*2+i), *(val+i) );
1295: }
1296: break;
1297: case aggSTD:
1298: for(i=0; i<OptFld->flds->cnt; i++){
1299: *(val+i)=mssVsqrt(mssVdiv(*(val+OptFld->flds->cnt*2+i), mssVsub(*(val+i),const1)));
1300: }
1301: break;
1302: case aggSTDP:
1303: for(i=0; i<OptFld->flds->cnt; i++){
1304: *(val+i)=mssVsqrt(mssVdiv(*(val+OptFld->flds->cnt*2+i), *(val+i)));
1305: }
1306: break;
1307: }
1308:
1309: for(i=0; i<FldCnt-1; i++){
1310: if(*(OptFld->fldNo2optNo+i)==-1){
1311: mssWriteStr(*(fld+i),fpw);
1312: }else{
1313: mssVwriteDbl(*(val+*(OptFld->fldNo2optNo+i)), fpw);
1314: }
1315: mssWriteDlm(fpw);
1316: }
1317: if(*(OptFld->fldNo2optNo+i)==-1){
1318: mssWriteStr(*(fld+i),fpw);
1319: }else{
1320: mssVwriteDbl(*(val+*(OptFld->fldNo2optNo+i)), fpw);
1321: }
1322: mssWriteRet(fpw);
1323: }
1324:
1325: /**
1326: * # FUNCTION #
1327: * 集計タイプに応じて、最終結果を計算し、一行出力する。
1328: *文字列としての項目をvalに変換する関数
1329: *valはrbtreeに入れるための一時的なもの
1330: */
1331: void mssSetAggVal(MssValue *val, char **str)
1332: {
1333: int i;
1334: for(i=0; i<OptFld->flds->cnt; i++){
1335: if( MssIsNull(*(str+MssFlds2num(OptFld->flds,i))) ){
1336: MssVnull(*(val+i));
1337: }else{
1338: (val+i)->nul=0;
1339: (val+i)->v.d=atof(*(str+MssFlds2num(OptFld->flds,i)));
1340: }
1341: }
1342: }
1343:
1344: /**
1345: * # FUNCTION #
1346: * RBキューを用いた項目切り分け型行読み込み
1347: * 既に並べ変わっているバケット(ad->iStartからad->iEnd)を集計しながら
1348: * 併合していく
1349: * ファイルの個数は既にPWayA以下になっていることが前提
1350: */
1351: int mssReadWriteAgg(struct mssAggDat *ad, struct mssFPW *oFile)
1352: {
1353: struct RBAGnode *node; /*popにて取りだしたノードを格納*/
1354: int bkt[PWayA];/*Pway併合時にRBtreeからpopしたデータのバケットNo*/
1355: int bktCnt; /*そのバケット数*/
1356: int i;
1357:
1358: node=RBAGpop(ad->rb->left); /*キューから一行取り出し*/
1359: if(strcmp(node->key->str,readEnd)==0) /*readEnd(番兵)を取り出したら終了*/
1360: return(EOF);
1361:
1362: /*一行書き出し*/
1363: mssWriteAggFld(node->key->fld,node->key->val,AGGType,oFile);
1364:
1365: bktCnt=0; /*popで取り出したkey値のバケット数*/
1366: for(i=0; i<PWayA; i++){
1367: if(*(node->key->bkt+i) == 1)
1368: bkt[bktCnt++]=i; /*バケットフラグをセット*/
1369: }
1370: RBAGdeleteNode(node); /*取り出したノードの削除*/
1371:
1372: /*popしたバケットから新に読みこんでRBtreeに挿入する*/
1373: for(i=0; i<bktCnt; i++){
1374: readRBAGkey(ad->iFile[bkt[i]],ad->fr[bkt[i]]);
1375: fread(ad->val,sizeof(MssValue),ad->valCnt,ad->vFile[bkt[i]]);
1376: RBAGinsert(ad->rb->left,ad->fr[bkt[i]],bkt[i],ad->val);
1377: }
1378: return(1); /*とりあえず*/
1379: }
1380:
1381: /**
1382: * # FUNCTION #
1383: *赤黒木を作りながら集計+集計しながらPWayマージソート
1384: */
1385: void mssPreAgg(struct mssAggDat *ad, struct mssFPR *iFile)
1386: {
1387: /*シグナルハンドラの設定*/
1388: mssGV.usedTempFileFlg=1;
1389: mssSetSignalHandler();
1390:
1391: sortAG(ad,iFile);
1392: AGGType=chgAggType(AGGType);
1393: mergeRBAG(ad);
1394: setFirstLineRBAG(ad, ad->iStart,ad->iEnd);
1395: }
1396:
1397: /**
1398: * # FUNCTION #
1399: * mssAggDat構造体を初期化し、そのポインタを返す。
1400: */
1401: struct mssAggDat *mssInitAggDat(int fldCnt, MssOptKEY *optKey, MssOptFLD *optFld, char *aggType, char *tmpDir, int *inCnt)
1402: {
1403: struct mssAggDat *aggDat;
1404: aggDat=mssMalloc(sizeof(struct mssAggDat),"initAggDat");
1405:
1406: aggDat->fldCnt = fldCnt;
1407: aggDat->optKey = optKey;
1408: aggDat->optFld = optFld;
1409: aggDat->aggType = setAggType(aggType);
1410: aggDat->tmpDir = tmpDir;
1411: aggDat->inCnt = inCnt;
1412: aggDat->val = getAggValMem(aggDat->aggType, aggDat->optFld->flds->cnt);
1413: aggDat->valCnt = getAggValCnt(aggDat->aggType, aggDat->optFld->flds->cnt);
1414: aggDat->aggVal = getAggValMem(aggDat->aggType, aggDat->optFld->flds->cnt);
1415:
1416: /*グローバル変数*/
1417: FldCnt = aggDat->fldCnt;
1418: OptKey = aggDat->optKey;
1419: OptFld = aggDat->optFld;
1420: AGGType = aggDat->aggType;
1421:
1422: return(aggDat);
1423: }
1424:
1425: /**
1426: * # FUNCTION #
1427: * mssAggDat構造体の開放。
1428: */
1429: void mssFreeAggDat(struct mssAggDat *ad)
1430: {
1431: int i;
1432:
1433: if(ad->procType==1){
1434: /*バッファ管理のために、入力ファイルはここで初めてクローズする*/
1435: for(i=0; i<=ad->iEnd-ad->iStart; i++){
1436: mssCloseFPR(ad->iFile[i]);
1437: mssFreeFldRec(ad->fr[i]);
1438: }
1439:
1440: /*ファイルの削除*/
1441: for(i=ad->iStart; i<=ad->iEnd; i++){
1442: unlink(getFname(ad->prefixTxt,i));
1443: unlink(getFname(ad->prefixVal,i));
1444: }
1445:
1446: /*領域開放*/
1447: RBAGfree(ad->rb);
1448: }
1449: mssFree(ad->val);
1450: mssFree(ad->aggVal);
1451: mssFree(ad);
1452: }