00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #define _RULEBLD_SOURCE_
00034
00035 #include "setup.h"
00036
00037 #if DEFRULE_CONSTRUCT && (! RUN_TIME) && (! BLOAD_ONLY)
00038
00039 #include <stdio.h>
00040 #define _STDIO_INCLUDED_
00041 #include <stdlib.h>
00042
00043 #include "constant.h"
00044 #include "envrnmnt.h"
00045 #include "constrct.h"
00046 #include "drive.h"
00047 #include "incrrset.h"
00048 #include "memalloc.h"
00049 #include "pattern.h"
00050 #include "reteutil.h"
00051 #include "router.h"
00052 #include "rulebld.h"
00053 #include "watch.h"
00054
00055
00056
00057
00058
00059 static struct joinNode *FindShareableJoin(struct joinLink *,struct joinNode *,intBool,void *,unsigned,unsigned,
00060 unsigned,unsigned,struct expr *,struct expr *,
00061 struct expr *,struct expr *);
00062 static int TestJoinForReuse(struct joinNode *,unsigned,unsigned,
00063 unsigned,unsigned,struct expr *,struct expr *,
00064 struct expr *,struct expr *);
00065 static struct joinNode *CreateNewJoin(void *,struct expr *,struct expr *,struct joinNode *,void *,
00066 int,int,int,struct expr *,struct expr *);
00067 static void AttachTestCEsToPatternCEs(void *,struct lhsParseNode *);
00068
00069
00070
00071
00072
00073 globle struct joinNode *ConstructJoins(
00074 void *theEnv,
00075 int logicalJoin,
00076 struct lhsParseNode *theLHS,
00077 int startDepth)
00078 {
00079 struct joinNode *lastJoin = NULL;
00080 struct patternNodeHeader *lastPattern;
00081 unsigned firstJoin = TRUE;
00082 int tryToReuse = TRUE;
00083 struct joinNode *listOfJoins = NULL;
00084 struct joinNode *oldJoin;
00085 int joinNumber = 1;
00086 int isLogical, isExists;
00087 struct joinNode *lastRightJoin;
00088 int lastIteration = FALSE;
00089 int rhsType;
00090 struct expr *leftHash, *rightHash;
00091 void *rhsStruct;
00092 struct lhsParseNode *nextLHS;
00093 struct expr *networkTest, *secondaryNetworkTest, *secondaryExternalTest;
00094 int joinFromTheRight;
00095 struct joinLink *theLinks;
00096 intBool useLinks;
00097
00098
00099
00100
00101
00102
00103
00104 if (startDepth == 1)
00105 { AttachTestCEsToPatternCEs(theEnv,theLHS); }
00106
00107 if (theLHS == NULL)
00108 {
00109 lastJoin = FindShareableJoin(DefruleData(theEnv)->RightPrimeJoins,NULL,TRUE,NULL,TRUE,
00110 FALSE,FALSE,FALSE,NULL,NULL,NULL,NULL);
00111
00112 if (lastJoin == NULL)
00113 { lastJoin = CreateNewJoin(theEnv,NULL,NULL,NULL,NULL,FALSE,FALSE,FALSE,NULL,NULL); }
00114 }
00115
00116
00117
00118
00119
00120
00121 while (theLHS != NULL)
00122 {
00123
00124
00125
00126
00127
00128
00129
00130
00131 nextLHS = theLHS->bottom;
00132 secondaryExternalTest = NULL;
00133
00134 if (theLHS->endNandDepth > startDepth)
00135 {
00136 while ((nextLHS != NULL) &&
00137 (nextLHS->endNandDepth > startDepth))
00138 { nextLHS = nextLHS->bottom; }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 if (nextLHS != NULL)
00149 {
00150 if (nextLHS->endNandDepth < startDepth)
00151 { lastIteration = TRUE; }
00152 }
00153
00154 if (nextLHS != NULL)
00155 { nextLHS = nextLHS->bottom; }
00156
00157 if ((nextLHS != NULL) && (nextLHS->type == TEST_CE))
00158 {
00159 secondaryExternalTest = nextLHS->networkTest;
00160 nextLHS = nextLHS->bottom;
00161 }
00162 }
00163
00164
00165
00166
00167
00168 if (nextLHS == NULL)
00169 { lastIteration = TRUE; }
00170 else if (theLHS->endNandDepth < startDepth)
00171 { lastIteration = TRUE; }
00172 else if ((nextLHS->type == TEST_CE) &&
00173 (theLHS->beginNandDepth > startDepth) &&
00174 (nextLHS->endNandDepth < startDepth))
00175 { lastIteration = TRUE; }
00176
00177
00178
00179
00180
00181
00182
00183 if (theLHS->beginNandDepth > startDepth)
00184 {
00185 joinFromTheRight = TRUE;
00186 isExists = theLHS->existsNand;
00187
00188 lastRightJoin = ConstructJoins(theEnv,logicalJoin,theLHS,startDepth+1);
00189
00190 rhsStruct = lastRightJoin;
00191 rhsType = 0;
00192 lastPattern = NULL;
00193 networkTest = theLHS->externalNetworkTest;
00194 secondaryNetworkTest = secondaryExternalTest;
00195 leftHash = theLHS->externalLeftHash;
00196 rightHash = theLHS->externalRightHash;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 else if (theLHS->right == NULL)
00206 {
00207 joinFromTheRight = FALSE;
00208 rhsType = 0;
00209 lastPattern = NULL;
00210 rhsStruct = NULL;
00211 lastRightJoin = NULL;
00212 isExists = theLHS->exists;
00213 networkTest = theLHS->networkTest;
00214 secondaryNetworkTest = theLHS->secondaryNetworkTest;
00215 leftHash = NULL;
00216 rightHash = NULL;
00217 }
00218 else
00219 {
00220 joinFromTheRight = FALSE;
00221 rhsType = theLHS->patternType->positionInArray;
00222 lastPattern = (*theLHS->patternType->addPatternFunction)(theEnv,theLHS);
00223 rhsStruct = lastPattern;
00224 lastRightJoin = NULL;
00225 isExists = theLHS->exists;
00226 networkTest = theLHS->networkTest;
00227 secondaryNetworkTest = theLHS->secondaryNetworkTest;
00228 leftHash = theLHS->leftHash;
00229 rightHash = theLHS->rightHash;
00230 }
00231
00232
00233
00234
00235
00236 if ((startDepth == 1) && (joinNumber == logicalJoin)) isLogical = TRUE;
00237 else isLogical = FALSE;
00238
00239
00240
00241
00242
00243
00244 useLinks = TRUE;
00245 if (firstJoin == TRUE)
00246 {
00247 if (theLHS->right == NULL)
00248 { theLinks = DefruleData(theEnv)->RightPrimeJoins; }
00249 else if (lastPattern != NULL)
00250 {
00251 listOfJoins = lastPattern->entryJoin;
00252 theLinks = NULL;
00253 useLinks = FALSE;
00254 }
00255 else
00256 { theLinks = lastRightJoin->nextLinks; }
00257 }
00258 else
00259 { theLinks = lastJoin->nextLinks; }
00260
00261
00262
00263
00264
00265 if ((tryToReuse == TRUE) &&
00266 ((oldJoin = FindShareableJoin(theLinks,listOfJoins,useLinks,rhsStruct,firstJoin,
00267 theLHS->negated,isExists,isLogical,
00268 networkTest,secondaryNetworkTest,
00269 leftHash,rightHash)) != NULL) )
00270 {
00271 #if DEBUGGING_FUNCTIONS
00272 if ((EnvGetWatchItem(theEnv,"compilations") == TRUE) && GetPrintWhileLoading(theEnv))
00273 { EnvPrintRouter(theEnv,WDIALOG,"=j"); }
00274 #endif
00275 lastJoin = oldJoin;
00276 }
00277 else
00278 {
00279 tryToReuse = FALSE;
00280 if (! joinFromTheRight)
00281 {
00282 lastJoin = CreateNewJoin(theEnv,networkTest,secondaryNetworkTest,lastJoin,
00283 lastPattern,FALSE,(int) theLHS->negated, isExists,
00284 leftHash,rightHash);
00285 lastJoin->rhsType = rhsType;
00286 }
00287 else
00288 {
00289 lastJoin = CreateNewJoin(theEnv,networkTest,secondaryNetworkTest,lastJoin,
00290 lastRightJoin,TRUE,(int) theLHS->negated, isExists,
00291 leftHash,rightHash);
00292 lastJoin->rhsType = rhsType;
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301 if (lastIteration)
00302 { break; }
00303
00304
00305
00306
00307
00308 theLHS = nextLHS;
00309 joinNumber++;
00310 firstJoin = FALSE;
00311 }
00312
00313
00314
00315
00316
00317
00318 if (startDepth == 1)
00319 {
00320 lastJoin = CreateNewJoin(theEnv,NULL,NULL,lastJoin,NULL,
00321 FALSE,FALSE,FALSE,NULL,NULL);
00322 }
00323
00324
00325
00326
00327
00328
00329 #if DEBUGGING_FUNCTIONS
00330 if ((startDepth == 1) &&
00331 (EnvGetWatchItem(theEnv,"compilations") == TRUE) &&
00332 GetPrintWhileLoading(theEnv))
00333 { EnvPrintRouter(theEnv,WDIALOG,"\n"); }
00334 #endif
00335
00336
00337
00338
00339
00340 return(lastJoin);
00341 }
00342
00343
00344
00345
00346
00347
00348 static void AttachTestCEsToPatternCEs(
00349 void *theEnv,
00350 struct lhsParseNode *theLHS)
00351 {
00352 struct lhsParseNode *lastNode, *tempNode;
00353
00354 if (theLHS == NULL) return;
00355
00356
00357
00358
00359
00360 lastNode = theLHS;
00361 theLHS = lastNode->bottom;
00362
00363 while (theLHS != NULL)
00364 {
00365 if ((theLHS->type != TEST_CE) ||
00366 (lastNode->beginNandDepth != lastNode->endNandDepth) ||
00367 (lastNode->beginNandDepth != theLHS->beginNandDepth))
00368 {
00369 lastNode = theLHS;
00370 theLHS = theLHS->bottom;
00371 continue;
00372 }
00373
00374 if (lastNode->negated)
00375 {
00376 lastNode->secondaryNetworkTest =
00377 CombineExpressions(theEnv,lastNode->secondaryNetworkTest,theLHS->networkTest);
00378 }
00379 else
00380 {
00381 lastNode->networkTest =
00382 CombineExpressions(theEnv,lastNode->networkTest,theLHS->networkTest);
00383 }
00384
00385 theLHS->networkTest = NULL;
00386 tempNode = theLHS->bottom;
00387 theLHS->bottom = NULL;
00388 lastNode->bottom = tempNode;
00389 lastNode->endNandDepth = theLHS->endNandDepth;
00390 ReturnLHSParseNodes(theEnv,theLHS);
00391 theLHS = tempNode;
00392 }
00393 }
00394
00395
00396
00397
00398
00399
00400
00401 static struct joinNode *FindShareableJoin(
00402 struct joinLink *theLinks,
00403 struct joinNode *listOfJoins,
00404 intBool useLinks,
00405 void *rhsStruct,
00406 unsigned int firstJoin,
00407 unsigned int negatedRHS,
00408 unsigned int existsRHS,
00409 unsigned int isLogical,
00410 struct expr *joinTest,
00411 struct expr *secondaryJoinTest,
00412 struct expr *leftHash,
00413 struct expr *rightHash)
00414 {
00415
00416
00417
00418
00419
00420 if (useLinks)
00421 {
00422 if (theLinks != NULL)
00423 { listOfJoins = theLinks->join; }
00424 else
00425 { listOfJoins = NULL; }
00426 }
00427
00428 while (listOfJoins != NULL)
00429 {
00430
00431
00432
00433
00434
00435
00436
00437 if (listOfJoins->rightSideEntryStructure == rhsStruct)
00438 {
00439 if (TestJoinForReuse(listOfJoins,firstJoin,negatedRHS,existsRHS,
00440 isLogical,joinTest,secondaryJoinTest,
00441 leftHash,rightHash))
00442 { return(listOfJoins); }
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 if (useLinks)
00455 {
00456 theLinks = theLinks->next;
00457 if (theLinks != NULL)
00458 { listOfJoins = theLinks->join; }
00459 else
00460 { listOfJoins = NULL; }
00461 }
00462 else
00463 { listOfJoins = listOfJoins->rightMatchNode; }
00464 }
00465
00466
00467
00468
00469
00470
00471 return(NULL);
00472 }
00473
00474
00475
00476
00477
00478
00479 static int TestJoinForReuse(
00480 struct joinNode *testJoin,
00481 unsigned firstJoin,
00482 unsigned negatedRHS,
00483 unsigned existsRHS,
00484 unsigned int isLogical,
00485 struct expr *joinTest,
00486 struct expr *secondaryJoinTest,
00487 struct expr *leftHash,
00488 struct expr *rightHash)
00489 {
00490
00491
00492
00493
00494
00495 if (testJoin->firstJoin != firstJoin) return(FALSE);
00496
00497
00498
00499
00500
00501
00502 if ((testJoin->patternIsNegated != negatedRHS) && (! existsRHS)) return(FALSE);
00503
00504
00505
00506
00507
00508
00509 if (testJoin->patternIsExists != existsRHS) return(FALSE);
00510
00511
00512
00513
00514
00515
00516
00517
00518 if ((isLogical == TRUE) &&
00519 (testJoin->logicalJoin == FALSE) &&
00520 BetaMemoryNotEmpty(testJoin))
00521 { return(FALSE); }
00522
00523
00524
00525
00526
00527
00528 if (IdenticalExpression(testJoin->networkTest,joinTest) != TRUE)
00529 { return(FALSE); }
00530
00531 if (IdenticalExpression(testJoin->secondaryNetworkTest,secondaryJoinTest) != TRUE)
00532 { return(FALSE); }
00533
00534
00535
00536
00537
00538
00539 if (IdenticalExpression(testJoin->leftHash,leftHash) != TRUE)
00540 { return(FALSE); }
00541
00542 if (IdenticalExpression(testJoin->rightHash,rightHash) != TRUE)
00543 { return(FALSE); }
00544
00545
00546
00547
00548
00549
00550 return(TRUE);
00551 }
00552
00553
00554
00555
00556 static struct joinNode *CreateNewJoin(
00557 void *theEnv,
00558 struct expr *joinTest,
00559 struct expr *secondaryJoinTest,
00560 struct joinNode *lhsEntryStruct,
00561 void *rhsEntryStruct,
00562 int joinFromTheRight,
00563 int negatedRHSPattern,
00564 int existsRHSPattern,
00565 struct expr *leftHash,
00566 struct expr *rightHash)
00567 {
00568 struct joinNode *newJoin;
00569 struct joinLink *theLink;
00570
00571
00572
00573
00574
00575
00576
00577
00578 #if DEBUGGING_FUNCTIONS
00579 if ((EnvGetWatchItem(theEnv,"compilations") == TRUE) && GetPrintWhileLoading(theEnv))
00580 { EnvPrintRouter(theEnv,WDIALOG,"+j"); }
00581 #endif
00582
00583
00584
00585
00586
00587 newJoin = get_struct(theEnv,joinNode);
00588
00589
00590
00591
00592
00593
00594 if ((lhsEntryStruct != NULL) || existsRHSPattern || negatedRHSPattern || joinFromTheRight)
00595 {
00596 if (leftHash == NULL)
00597 {
00598 newJoin->leftMemory = get_struct(theEnv,betaMemory);
00599 newJoin->leftMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
00600 newJoin->leftMemory->beta[0] = NULL;
00601 newJoin->leftMemory->size = 1;
00602 newJoin->leftMemory->count = 0;
00603 }
00604 else
00605 {
00606 newJoin->leftMemory = get_struct(theEnv,betaMemory);
00607 newJoin->leftMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
00608 memset(newJoin->leftMemory->beta,0,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
00609 newJoin->leftMemory->size = INITIAL_BETA_HASH_SIZE;
00610 newJoin->leftMemory->count = 0;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620 if ((lhsEntryStruct == NULL) && (existsRHSPattern || negatedRHSPattern || joinFromTheRight))
00621 {
00622 newJoin->leftMemory->beta[0] = CreateEmptyPartialMatch(theEnv);
00623 newJoin->leftMemory->beta[0]->owner = newJoin;
00624 newJoin->leftMemory->count = 1;
00625 }
00626 }
00627 else
00628 { newJoin->leftMemory = NULL; }
00629
00630 if (joinFromTheRight)
00631 {
00632 if (leftHash == NULL)
00633 {
00634 newJoin->rightMemory = get_struct(theEnv,betaMemory);
00635 newJoin->rightMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
00636 newJoin->rightMemory->last = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
00637 newJoin->rightMemory->beta[0] = NULL;
00638 newJoin->rightMemory->last[0] = NULL;
00639 newJoin->rightMemory->size = 1;
00640 newJoin->rightMemory->count = 0;
00641 }
00642 else
00643 {
00644 newJoin->rightMemory = get_struct(theEnv,betaMemory);
00645 newJoin->rightMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
00646 newJoin->rightMemory->last = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
00647 memset(newJoin->rightMemory->beta,0,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
00648 memset(newJoin->rightMemory->last,0,sizeof(struct partialMatch *) * INITIAL_BETA_HASH_SIZE);
00649 newJoin->rightMemory->size = INITIAL_BETA_HASH_SIZE;
00650 newJoin->rightMemory->count = 0;
00651 }
00652 }
00653 else if ((lhsEntryStruct == NULL) && (rhsEntryStruct == NULL))
00654 {
00655 newJoin->rightMemory = get_struct(theEnv,betaMemory);
00656 newJoin->rightMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
00657 newJoin->rightMemory->last = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *));
00658 newJoin->rightMemory->beta[0] = CreateEmptyPartialMatch(theEnv);
00659 newJoin->rightMemory->beta[0]->owner = newJoin;
00660 newJoin->rightMemory->beta[0]->rhsMemory = TRUE;
00661 newJoin->rightMemory->last[0] = newJoin->rightMemory->beta[0];
00662 newJoin->rightMemory->size = 1;
00663 newJoin->rightMemory->count = 1;
00664 }
00665 else
00666 { newJoin->rightMemory = NULL; }
00667
00668 newJoin->nextLinks = NULL;
00669 newJoin->joinFromTheRight = joinFromTheRight;
00670
00671 if (existsRHSPattern)
00672 { newJoin->patternIsNegated = FALSE; }
00673 else
00674 { newJoin->patternIsNegated = negatedRHSPattern; }
00675 newJoin->patternIsExists = existsRHSPattern;
00676
00677 newJoin->marked = FALSE;
00678 newJoin->initialize = EnvGetIncrementalReset(theEnv);
00679 newJoin->logicalJoin = FALSE;
00680 newJoin->ruleToActivate = NULL;
00681 newJoin->memoryAdds = 0;
00682 newJoin->memoryDeletes = 0;
00683 newJoin->memoryCompares = 0;
00684
00685
00686
00687
00688
00689
00690
00691 newJoin->networkTest = AddHashedExpression(theEnv,joinTest);
00692 newJoin->secondaryNetworkTest = AddHashedExpression(theEnv,secondaryJoinTest);
00693
00694
00695
00696
00697
00698
00699
00700 newJoin->leftHash = AddHashedExpression(theEnv,leftHash);
00701 newJoin->rightHash = AddHashedExpression(theEnv,rightHash);
00702
00703
00704
00705
00706
00707 newJoin->lastLevel = lhsEntryStruct;
00708
00709 if (lhsEntryStruct == NULL)
00710 {
00711 newJoin->firstJoin = TRUE;
00712 newJoin->depth = 1;
00713 }
00714 else
00715 {
00716 newJoin->firstJoin = FALSE;
00717 newJoin->depth = lhsEntryStruct->depth;
00718 newJoin->depth++;
00719
00720 theLink = get_struct(theEnv,joinLink);
00721 theLink->join = newJoin;
00722 theLink->enterDirection = LHS;
00723 theLink->next = lhsEntryStruct->nextLinks;
00724 lhsEntryStruct->nextLinks = theLink;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733 newJoin->rightSideEntryStructure = rhsEntryStruct;
00734
00735 if (rhsEntryStruct == NULL)
00736 {
00737 if (newJoin->firstJoin)
00738 {
00739 theLink = get_struct(theEnv,joinLink);
00740 theLink->join = newJoin;
00741 theLink->enterDirection = RHS;
00742 theLink->next = DefruleData(theEnv)->RightPrimeJoins;
00743 DefruleData(theEnv)->RightPrimeJoins = theLink;
00744 }
00745
00746 newJoin->rightMatchNode = NULL;
00747
00748 return(newJoin);
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 if (newJoin->firstJoin && (newJoin->patternIsNegated || newJoin->joinFromTheRight) && (! newJoin->patternIsExists))
00760 {
00761 theLink = get_struct(theEnv,joinLink);
00762 theLink->join = newJoin;
00763 theLink->enterDirection = LHS;
00764 theLink->next = DefruleData(theEnv)->LeftPrimeJoins;
00765 DefruleData(theEnv)->LeftPrimeJoins = theLink;
00766 }
00767
00768 if (joinFromTheRight)
00769 {
00770 theLink = get_struct(theEnv,joinLink);
00771 theLink->join = newJoin;
00772 theLink->enterDirection = RHS;
00773 theLink->next = ((struct joinNode *) rhsEntryStruct)->nextLinks;
00774 ((struct joinNode *) rhsEntryStruct)->nextLinks = theLink;
00775 newJoin->rightMatchNode = NULL;
00776 }
00777 else
00778 {
00779 newJoin->rightMatchNode = ((struct patternNodeHeader *) rhsEntryStruct)->entryJoin;
00780 ((struct patternNodeHeader *) rhsEntryStruct)->entryJoin = newJoin;
00781 }
00782
00783
00784
00785
00786
00787 return(newJoin);
00788 }
00789
00790 #endif
00791
00792
00793