List:Commits« Previous MessageNext Message »
From:U-ROWVWADEjas Date:May 7 2008 10:37pm
Subject:bk commit into 6.0 tree (jas:1.2671)
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of jas.  When jas does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-05-07 18:37:18-04:00, jas@rowvwade. +11 -0
  Got deferred index handling working for the "limit" optimization, at least to the
  first order.  Checking in for testing and safety.

  storage/falcon/DeferredIndexWalker.cpp@stripped, 2008-05-07 18:37:01-04:00, jas@rowvwade. +9 -0
    Split out initialization from constructor for the class WalkDeferred, part of the
    limit optimization.

  storage/falcon/DeferredIndexWalker.h@stripped, 2008-05-07 18:37:02-04:00, jas@rowvwade. +2 -0
    Split out initialization from constructor for the class WalkDeferred, part of the
    limit optimization.

  storage/falcon/Index.cpp@stripped, 2008-05-07 18:37:02-04:00, jas@rowvwade. +12 -19
    Implemented IndexWalk as the merge object for a single WalkIndex and
    an arbitrary set of WalkDeferred objects.

  storage/falcon/IndexRootPage.cpp@stripped, 2008-05-07 18:37:02-04:00, jas@rowvwade. +1 -1
    Changed the name of WalkIndex::key to WalkIndex::indexKey to reduce
    confusion and overloading.

  storage/falcon/IndexWalker.cpp@stripped, 2008-05-07 18:37:03-04:00, jas@rowvwade. +401 -2
    Merged AVLP (AVL w/ parent) code to manage the merge tree
    from independent walks of the on-disk index and one or more
    deferred indexes.

  storage/falcon/IndexWalker.h@stripped, 2008-05-07 18:37:03-04:00, jas@rowvwade. +25 -7
    Merged AVLP (AVL w/ parent) code to manage the merge tree
    from independent walks of the on-disk index and one or more
    deferred indexes.

  storage/falcon/WalkDeferred.cpp@stripped, 2008-05-07 18:37:04-04:00, jas@rowvwade. +25 -1
    Fleshed out code for walking deferred indexes for the "limit" optimizatin.

  storage/falcon/WalkDeferred.h@stripped, 2008-05-07 18:37:04-04:00, jas@rowvwade. +7 -1
    Fleshed out code for walking deferred indexes for the "limit" optimizatin.

  storage/falcon/WalkIndex.cpp@stripped, 2008-05-07 18:37:04-04:00, jas@rowvwade. +6 -3
    Minor refactoring of WalkIndex to make it work with the IndexWalk
    merge mechanism.

  storage/falcon/WalkIndex.h@stripped, 2008-05-07 18:37:05-04:00, jas@rowvwade. +1 -0
    Minor refactoring of WalkIndex to make it work with the IndexWalk
    merge mechanism.

  storage/myisammrg/scripts/mysql_config.pl@stripped, 2008-05-07 18:37:06-04:00, jas@rowvwade. +285 -0
    Handle hander::index_first for the "limit" optimization.

  storage/myisammrg/scripts/mysql_config.pl@stripped, 2008-05-07 18:37:06-04:00, jas@rowvwade. +0 -0

diff -Nrup a/storage/falcon/DeferredIndexWalker.cpp b/storage/falcon/DeferredIndexWalker.cpp
--- a/storage/falcon/DeferredIndexWalker.cpp	2007-09-20 11:41:38 -04:00
+++ b/storage/falcon/DeferredIndexWalker.cpp	2008-05-07 18:37:01 -04:00
@@ -19,7 +19,16 @@
 #include "IndexKey.h"
 #include "Index.h"
 
+DeferredIndexWalker::DeferredIndexWalker()
+{
+}
+
 DeferredIndexWalker::DeferredIndexWalker(DeferredIndex *deferredIdx, IndexKey *indexKey, int searchFlags)
+{
+	initialize(deferredIdx, indexKey, searchFlags);
+}
+
+void DeferredIndexWalker::initialize(DeferredIndex *deferredIdx, IndexKey *indexKey, int searchFlags)
 {
 	deferredIndex = deferredIdx;
 	currentNode = NULL;
diff -Nrup a/storage/falcon/DeferredIndexWalker.h b/storage/falcon/DeferredIndexWalker.h
--- a/storage/falcon/DeferredIndexWalker.h	2007-09-20 11:41:38 -04:00
+++ b/storage/falcon/DeferredIndexWalker.h	2008-05-07 18:37:02 -04:00
@@ -25,9 +25,11 @@ struct DINode;
 class DeferredIndexWalker
 {
 public:
+	DeferredIndexWalker();
 	DeferredIndexWalker(DeferredIndex *deferredIdx, IndexKey *indexKey, int searchFlags = 0);
 	~DeferredIndexWalker(void);
 	
+	void		initialize(DeferredIndex *deferredIdx, IndexKey *indexKey, int searchFlags = 0);
 	DINode		*next(void);
 
 	DeferredIndex	*deferredIndex;
diff -Nrup a/storage/falcon/Index.cpp b/storage/falcon/Index.cpp
--- a/storage/falcon/Index.cpp	2008-05-02 18:09:08 -04:00
+++ b/storage/falcon/Index.cpp	2008-05-07 18:37:02 -04:00
@@ -487,7 +487,7 @@ IndexWalker* Index::positionIndex(IndexK
 		
 	ASSERT (indexId != -1);
 	WalkIndex *walkIndex = new WalkIndex(this, transaction, searchFlags, lowKey, highKey);
-	IndexWalker *indexWalker = walkIndex;
+	IndexWalker *indexWalker = NULL;
 	
 	if (rootPage == 0)
 		getRootPage();
@@ -502,33 +502,26 @@ IndexWalker* Index::positionIndex(IndexK
 			ASSERT(false);
 		}
 		
-	/*** pending transmogrificaion
-	if (deferredIndexes.first)
+	if (transaction && deferredIndexes.first)
 		{
-		Sync sync(&deferredIndexes.syncObject, "Index::scanIndex");
+		Sync sync(&deferredIndexes.syncObject, "Index::positionIndex");
 		sync.lock(Shared);
 		
-		if (transaction)
-			{
-			for (DeferredIndex *deferredIndex = deferredIndexes.first; deferredIndex; deferredIndex = deferredIndex->next)
+		for (DeferredIndex *deferredIndex = deferredIndexes.first; deferredIndex; deferredIndex = deferredIndex->next)
+			if (transaction->visible(deferredIndex->transaction, deferredIndex->transactionId, FOR_WRITING))
 				{
-				if (transaction->visible(deferredIndex->transaction, deferredIndex->transactionId, FOR_WRITING))
+				if (!indexWalker)
 					{
-					deferredIndex->scanIndex(lowKey, highKey, searchFlags, bitmap);
-					
-					if (transaction->database->dbb->debug & (DEBUG_KEYS & DEBUG_DEFERRED_INDEX))
-						deferredIndex->print();
+					indexWalker = new IndexWalker(this, transaction, searchFlags);
+					indexWalker->addWalker(walkIndex);
 					}
+				
+				WalkDeferred *walkDeferred = new WalkDeferred(deferredIndex, transaction, searchFlags, &walkIndex->lowerBound, &walkIndex->upperBound);
+				indexWalker->addWalker(walkDeferred);
 				}
-			}
-		else
-			for (DeferredIndex *deferredIndex = deferredIndexes.first; deferredIndex; deferredIndex = deferredIndex->next)
-				deferredIndex->scanIndex(lowKey, highKey, searchFlags, bitmap);
 		}
-	***/
 	
-	
-	return indexWalker;
+	return (indexWalker) ? indexWalker : walkIndex;
 }
 
 void Index::setIndex(int32 id)
diff -Nrup a/storage/falcon/IndexRootPage.cpp b/storage/falcon/IndexRootPage.cpp
--- a/storage/falcon/IndexRootPage.cpp	2008-05-06 11:52:05 -04:00
+++ b/storage/falcon/IndexRootPage.cpp	2008-05-07 18:37:02 -04:00
@@ -1138,7 +1138,7 @@ int32 IndexRootPage::getIndexRoot(Dbb* d
 
 void IndexRootPage::positionIndex(Dbb* dbb, int indexId, int32 rootPage, WalkIndex* walkIndex)
 {
-	IndexKey *key = &walkIndex->key;
+	IndexKey *key = &walkIndex->indexKey;
 	uint offset = 0;
 	IndexKey *lowKey = &walkIndex->lowerBound;
 	IndexKey *highKey = &walkIndex->upperBound;
diff -Nrup a/storage/falcon/IndexWalker.cpp b/storage/falcon/IndexWalker.cpp
--- a/storage/falcon/IndexWalker.cpp	2008-05-06 11:52:06 -04:00
+++ b/storage/falcon/IndexWalker.cpp	2008-05-07 18:37:03 -04:00
@@ -19,6 +19,13 @@
 #include "Table.h"
 #include "SQLError.h"
 
+#define RESET_PARENT(newChild)		\
+	if (parent->lower == this)		\
+		parent->lower = newChild;	 \
+	else							\
+		parent->higher = newChild;
+		
+
 IndexWalker::IndexWalker(Index *idx, Transaction *trans, int flags)
 {
 	index = idx;
@@ -26,15 +33,86 @@ IndexWalker::IndexWalker(Index *idx, Tra
 	transaction = trans;
 	searchFlags = flags;
 	currentRecord = NULL;
+	parent = NULL;
+	next = NULL;
 	first = true;
 }
 
 IndexWalker::~IndexWalker(void)
 {
+	if (next)
+		delete next;
 }
 
 Record* IndexWalker::getNext(bool lockForUpdate)
 {
+	// If this is the first time in, prime the data structures
+	
+	if (first)
+		{
+		first = false;
+		higher = NULL;
+		lower = NULL;
+		
+		for (IndexWalker *walker = next; walker; walker = walker->next)
+			while (walker->getNext(lockForUpdate))
+				{
+				walker->higher = NULL;
+				walker->lower = NULL;
+			
+				if (higher)
+					{
+					if (higher->insert(walker))
+						break;
+					}
+				else
+					{
+					higher = walker;
+					walker->parent = this;
+					walker->balance = 0;
+					
+					break;
+					}
+				}
+		}
+
+	for (IndexWalker *walker; (walker = higher);)
+		{
+		// Find the walker with the lowest key value
+		
+		while (walker->lower)
+			walker = walker->lower;
+		
+		// Save the record, then take the walker out of the tree
+		
+		Record *record = walker->currentRecord;
+		walker->remove();
+		
+		// Find the next record for the walker.  If successful, put it back in the tree
+		
+		while (walker->getNext(lockForUpdate))
+			{
+			walker->higher = NULL;
+			walker->lower = NULL;
+			
+			if (higher)
+				{
+				if (higher->insert(walker))
+					break;
+				}
+			else
+				{
+				higher = walker;
+				walker->parent = this;
+				walker->balance = 0;
+				
+				break;
+				}
+			}
+		
+		return record;
+		}
+		
 	return NULL;
 }
 
@@ -74,8 +152,8 @@ Record* IndexWalker::getValidatedRecord(
 	IndexKey recordKey;
 	index->makeKey(record, &recordKey);
 	
-	if (recordKey.keyLength != key.keyLength ||
-		memcmp(recordKey.key, key.key, key.keyLength) != 0)
+	if (recordKey.keyLength != keyLength ||
+		memcmp(recordKey.key, key, keyLength) != 0)
 		{
 		record->release();
 		
@@ -83,4 +161,325 @@ Record* IndexWalker::getValidatedRecord(
 		}
 	
 	return record;
+}
+
+void IndexWalker::addWalker(IndexWalker* walker)
+{
+	walker->next = next;
+	next = walker;
+}
+
+bool IndexWalker::insert(IndexWalker* newNode)
+{
+	// Find insertion point and insert new node as leaf
+	
+	for (IndexWalker *node = this; node;)
+		{
+		int comparison = compare(newNode, node);
+		
+		if (comparison < 0)
+			{
+			if (node->lower)
+				node = node->lower;
+			else
+				{
+				node->lower = newNode;
+				--node->balance;
+				
+				break;
+				}
+			}
+		else if (comparison > 0)
+			{
+			if (node->higher)
+				node = node->higher;
+			else
+				{
+				node->higher = newNode;
+				++node->balance;
+				
+				break;
+				}
+			}
+		else
+			{
+			//printf("Duplicate %d\n", value);
+			
+			return false;
+			}
+		}
+	
+	// New node is inserted.  Balance tree upwards
+	
+	newNode->parent = node;
+
+	for (IndexWalker *nodeParent; node->balance && (nodeParent = node->parent) && nodeParent->parent; node = nodeParent)
+		{
+		if (nodeParent->lower == node)
+			{
+			if (--nodeParent->balance < -1)
+				{
+				nodeParent->rebalance();
+				break;
+				}
+			}
+		else
+			{
+			if (++nodeParent->balance > +1)
+				{
+				nodeParent->rebalance();
+				break;
+				}
+			}
+		}
+	
+	return true;
+}
+
+/*
+ *  Rebalance an unbalanced tree.  This is used for insert
+ */
+ 
+void IndexWalker::rebalance(void)
+{
+	if (balance > 1)
+		{
+		if (higher->balance < 0)
+			higher->rotateRight();
+					
+		rotateLeft();
+		}
+	else if (balance < 1)
+		{
+		if (lower->balance > 0)
+			lower->rotateLeft();
+			
+		rotateRight();
+		}
+}
+
+/*
+ * Rebalance an unbalanced tree taking node of whether the tree got shallower.  This
+ * is used for deletion.
+ */
+ 
+bool IndexWalker::rebalanceDelete()
+{
+	if (balance > 1)
+		{
+		if (higher->balance < 0)
+			{
+			higher->rotateRight();
+			rotateLeft();
+			
+			return true;
+			}
+					
+		rotateLeft();
+		
+		return parent->balance == 0;
+		}
+		
+	if (balance < 1)
+		{
+		if (lower->balance > 0)
+			{
+			lower->rotateLeft();
+			rotateRight();
+			
+			return true;
+			}
+			
+		rotateRight();
+		
+		return parent->balance == 0;
+		}
+	
+	return false;
+}
+
+
+
+/*
+	Swap nodes A and B in a tree
+	
+			A					B
+		   / \                 / \
+		  a   B      =>       A   C
+		     / \			 / \
+		    b   c			a   b
+ */
+ 
+void IndexWalker::rotateLeft(void)
+{
+	IndexWalker *root = higher;
+	
+	if ( (higher = higher->lower) )
+		higher->parent = this;
+
+	root->lower = this;
+	balance -= (1 + MAX(root->balance, 0));
+	root->balance -= (1 - MIN(balance, 0));
+	RESET_PARENT(root);
+	root->parent = parent;
+	parent = root;
+}
+
+/*
+	Swap nodes B and A in a tree
+	
+			B                  A
+		   / \                / \
+		  A   b    =>        a   B            
+		 / \                    / \
+		a   c                  c   b
+ */
+ 
+void IndexWalker::rotateRight(void)
+{
+	IndexWalker *root = lower;
+	
+	if ( (lower = lower->higher) )
+		lower->parent = this;
+		
+	root->higher = this;
+	balance += (1 - MIN(root->balance, 0));
+	root->balance += (1 + MAX(balance, 0));
+	RESET_PARENT(root);
+	root->parent = parent;
+	parent = root;
+}
+
+/*
+ * Look for a success node for a node being remove with two children.  This
+ * requires that we find the next higher value, which is also the lowest value
+ * in the deletion nodes right sub-tree.
+ */
+ 
+IndexWalker* IndexWalker::getSuccessor(IndexWalker** parentPointer, bool *shallower)
+{
+	// If there's a lower node, recurse down it rebalancing
+	// if the subtree gets shallower
+	
+	if (lower)
+		{
+		int was = balance;
+		IndexWalker *node = lower->getSuccessor(&lower, shallower);
+
+		// If we got shallower, adjust balance and rebalance if necessary
+
+		if (*shallower)
+			{
+			if (++balance > 1)
+				*shallower = rebalanceDelete();
+			else if (!was && (*parentPointer)->balance)
+				*shallower = false;
+			}
+			
+		return node;
+		}
+	
+	// We're the bottom.  Remove us from our parent and we're done.
+	
+	RESET_PARENT(higher);
+	
+	if (higher)
+		higher->parent = parent;
+		
+	*shallower = true;
+
+	return this;
+}
+
+int IndexWalker::compare(IndexWalker* node1, IndexWalker* node2)
+{
+	int length = MIN(node1->keyLength, node2->keyLength);
+	
+	for (UCHAR *key1 = node1->key, *key2 = node2->key, *end = key1 + length; key1 < end;)
+		{
+		int c = *key1++ - * key2++;
+		
+		if (c)
+			return c;
+		}
+
+	int c = node1->keyLength - node2->keyLength;
+	
+	if (c)
+		return c;
+		
+	return node1->recordNumber - node2->recordNumber;
+}
+
+void IndexWalker::remove(void)
+{
+	// There are three cases a) No children, b) One child, c) Two children
+
+	if (!lower || !higher)
+		{
+		IndexWalker *next = (lower) ? lower : higher;
+		
+		if (next)
+			next->parent = parent;
+		
+		if (parent->lower == this)
+			{
+			parent->lower = next;
+			parent->rebalanceUpward(+1);
+			}
+		else
+			{
+			parent->higher = next;
+			parent->rebalanceUpward(-1);
+			}	
+		
+		return;	
+		}
+
+	// We're an equality with two children.  Bummer.  Find successor node (next higher value)
+	// and swap it into our place
+	
+	bool shallower;
+	IndexWalker *node = higher->getSuccessor(&higher, &shallower);
+	
+	if ( (node->lower = lower) )
+		lower->parent = node;
+		
+	if ( (node->higher = higher) )
+		higher->parent = node;
+		
+	node->balance = balance;
+	node->parent = parent;
+	RESET_PARENT(node);
+	
+	// If we got shallower, adjust balance and rebalance if necessary
+
+	if (shallower)
+		node->rebalanceUpward(-1);
+}
+
+void IndexWalker::rebalanceUpward(int delta)
+{
+	IndexWalker *node = this;
+	
+	for (;;)
+		{
+		IndexWalker *nodeParent = node->parent;
+		
+		if (!nodeParent)
+			return;
+
+		int parentDelta = (nodeParent->lower == node) ? 1 : -1;
+		node->balance += delta;
+		
+		if (node->balance == delta)
+			break;
+		
+		if (node->balance > 1 || node->balance < -1)
+			if (!node->rebalanceDelete())
+				break;
+		
+		delta = parentDelta;			
+		node = nodeParent;
+		}
 }
diff -Nrup a/storage/falcon/IndexWalker.h b/storage/falcon/IndexWalker.h
--- a/storage/falcon/IndexWalker.h	2008-05-06 11:52:06 -04:00
+++ b/storage/falcon/IndexWalker.h	2008-05-07 18:37:03 -04:00
@@ -30,15 +30,33 @@ public:
 	~IndexWalker(void);
 	
 	virtual Record*		getNext(bool lockForUpdate);
+
 	Record*				getValidatedRecord(int32 recordId, bool lockForUpdate);
+	int					compare(IndexWalker* node1, IndexWalker* node2);
+	void				addWalker(IndexWalker* walker);
+	bool				insert(IndexWalker* node);
+	void				rotateLeft(void);
+	void				rotateRight(void);
+	void				rebalance(void);
+	bool				rebalanceDelete();
+	IndexWalker*		getSuccessor(IndexWalker** parentPointer, bool *shallower);
+	void				remove(void);
+	void				rebalanceUpward(int delta);
 	
-	Index		*index;
-	Transaction	*transaction;
-	IndexKey	key;
-	Record		*currentRecord;
-	Table		*table;
-	int			searchFlags;
-	bool		first;
+	Index			*index;
+	Transaction		*transaction;
+	Record			*currentRecord;
+	Table			*table;
+	IndexWalker		*next;
+	IndexWalker		*higher;
+	IndexWalker		*lower;
+	IndexWalker		*parent;
+	UCHAR			*key;
+	int				keyLength;
+	int32			recordNumber;
+	int				balance;
+	int				searchFlags;
+	bool			first;
 };
 
 #endif
diff -Nrup a/storage/falcon/WalkDeferred.cpp b/storage/falcon/WalkDeferred.cpp
--- a/storage/falcon/WalkDeferred.cpp	2008-05-02 18:09:13 -04:00
+++ b/storage/falcon/WalkDeferred.cpp	2008-05-07 18:37:04 -04:00
@@ -16,10 +16,34 @@
 #include "Engine.h"
 #include "WalkDeferred.h"
 
-WalkDeferred::WalkDeferred(Index *index, Transaction *transaction, int flags) : IndexWalker(index, transaction, flags)
+WalkDeferred::WalkDeferred(DeferredIndex *deferredIndex, Transaction *transaction, int flags, IndexKey *lower, IndexKey *upper) 
+	: IndexWalker(deferredIndex->index, transaction, flags)
 {
+	walker.initialize(deferredIndex, lower, flags);
 }
 
 WalkDeferred::~WalkDeferred(void)
 {
+}
+
+Record* WalkDeferred::getNext(bool lockForUpdate)
+{
+	for (;;)
+		{
+		node = walker.next();
+		
+		if (!node)
+			{
+			currentRecord = NULL;
+			
+			return NULL;
+			}
+
+		key = node->key;
+		keyLength = node->keyLength;
+		recordNumber = node->recordNumber;
+		
+		if ( (currentRecord = getValidatedRecord(recordNumber, lockForUpdate)) )
+			return currentRecord;
+		}
 }
diff -Nrup a/storage/falcon/WalkDeferred.h b/storage/falcon/WalkDeferred.h
--- a/storage/falcon/WalkDeferred.h	2008-05-02 18:09:13 -04:00
+++ b/storage/falcon/WalkDeferred.h	2008-05-07 18:37:04 -04:00
@@ -17,12 +17,18 @@
 #define _WALK_DEFERRED_H_
 
 #include "IndexWalker.h"
+#include "DeferredIndexWalker.h"
 
 class WalkDeferred : public IndexWalker
 {
 public:
-	WalkDeferred(Index *index, Transaction *transaction, int flags);
+	WalkDeferred(DeferredIndex *deferredIndex, Transaction *transaction, int flags, IndexKey *lower, IndexKey *upper);
 	virtual ~WalkDeferred(void);
+
+	virtual Record*		getNext(bool lockForUpdate);
+	
+	DeferredIndexWalker		walker;
+	DINode					*node;
 };
 
 #endif
diff -Nrup a/storage/falcon/WalkIndex.cpp b/storage/falcon/WalkIndex.cpp
--- a/storage/falcon/WalkIndex.cpp	2008-05-06 11:52:07 -04:00
+++ b/storage/falcon/WalkIndex.cpp	2008-05-07 18:37:04 -04:00
@@ -42,6 +42,7 @@ WalkIndex::WalkIndex(Index *index, Trans
 		upperBound.setKey(upper);
 	
 	nodes = new UCHAR[transaction->database->dbb->pageSize];
+	key = indexKey.key;
 }
 
 WalkIndex::~WalkIndex(void)
@@ -70,6 +71,8 @@ Record* WalkIndex::getNext(bool lockForU
 			return NULL;
 			}
 		
+		keyLength = indexKey.keyLength;
+		
 		if ( (currentRecord = getValidatedRecord(recordNumber, lockForUpdate)) )
 			return currentRecord;
 		}
@@ -82,7 +85,7 @@ int32 WalkIndex::getNextNode(void)
 		if (first)
 			{
 			first = false;
-			int32 recordNumber = node.getNumber();
+			recordNumber = node.getNumber();
 			
 			if (recordNumber >= 0)
 				return recordNumber;
@@ -92,8 +95,8 @@ int32 WalkIndex::getNextNode(void)
 		
 		if (node.node < endNodes)
 			{
-			int32 recordNumber = node.getNumber();
-			node.expandKey(&key);
+			recordNumber = node.getNumber();
+			node.expandKey(&indexKey);
 			
 			if (recordNumber >= 0)
 				return recordNumber;
diff -Nrup a/storage/falcon/WalkIndex.h b/storage/falcon/WalkIndex.h
--- a/storage/falcon/WalkIndex.h	2008-05-06 11:52:07 -04:00
+++ b/storage/falcon/WalkIndex.h	2008-05-07 18:37:05 -04:00
@@ -38,6 +38,7 @@ public:
 	IndexKey	upperBound;
 	UCHAR		*nodes;
 	IndexNode	node;
+	IndexKey	indexKey;
 	Btn			*endNodes;
 	int32		nextPage;
 };
diff -Nrup a/storage/myisammrg/scripts/mysql_config.pl b/storage/myisammrg/scripts/mysql_config.pl
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/storage/myisammrg/scripts/mysql_config.pl	2008-05-07 18:37:06 -04:00
@@ -0,0 +1,285 @@
+#!/usr/bin/perl
+# -*- cperl -*-
+#
+# Copyright (C) 2007 MySQL AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# 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.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+##############################################################################
+#
+#  This script reports various configuration settings that may be needed
+#  when using the MySQL client library.
+#
+#  This script try to match the shell script version as close as possible,
+#  but in addition being compatible with ActiveState Perl on Windows.
+#
+#  All unrecognized arguments to this script are passed to mysqld.
+#
+#  NOTE: This script will only be used on Windows until solved how to
+#        handle  and other strings inserted that might contain
+#        several arguments, possibly with spaces in them.
+#
+#  NOTE: This script was deliberately written to be as close to the shell
+#        script as possible, to make the maintenance of both in parallel
+#        easier.
+#
+##############################################################################
+
+use File::Basename;
+use Getopt::Long;
+use Cwd;
+use strict;
+
+my @exclude_cflags =
+  qw/DDBUG_OFF DSAFEMALLOC USAFEMALLOC DSAFE_MUTEX
+     DPEDANTIC_SAFEMALLOC DUNIV_MUST_NOT_INLINE DFORCE_INIT_OF_VARS
+     DEXTRA_DEBUG DHAVE_purify O O[0-9] xO[0-9] W[-A-Za-z]*
+     Xa xstrconst xc99=none
+     unroll2 ip mp restrict/;
+
+my @exclude_libs = qw/lmtmalloc static-libcxa i-static static-intel/;
+
+my $cwd = cwd();
+my $basedir;
+
+my $socket  = '/tmp/mysql.sock';
+my $version = '6.0.6-alpha';
+
+sub which
+{
+  my $file = shift;
+
+  my $IFS = $^O eq "MSWin32" ? ";" : ":";
+
+  foreach my $dir ( split($IFS, $ENV{PATH}) )
+  {
+    if ( -f "$dir/$file" or -f "$dir/$file.exe" )
+    {
+      return "$dir/$file";
+    }
+  }
+  print STDERR "which: no $file in ($ENV{PATH})\n";
+  exit 1;
+}
+
+# ----------------------------------------------------------------------
+# If we can find the given directory relatively to where mysql_config is
+# we should use this instead of the incompiled one.
+# This is to ensure that this script also works with the binary MySQL
+# version
+# ----------------------------------------------------------------------
+
+sub fix_path
+{
+  my $default = shift;
+  my @dirs = @_;
+
+  foreach my $dirname ( @dirs )
+  {
+    my $path = "$basedir/$dirname";
+    if ( -d $path )
+    {
+      return $path;
+    }
+  }
+  return $default;
+}
+
+sub get_full_path
+{
+  my $file = shift;
+
+  # if the file is a symlink, try to resolve it
+  if ( $^O ne "MSWin32" and -l $file )
+  {
+    $file = readlink($file);
+  }
+
+  if ( $file =~ m,^/, )
+  {
+    # Do nothing, absolute path
+  }
+  elsif ( $file =~ m,/, )
+  {
+    # Make absolute, and remove "/./" in path
+    $file = "$cwd/$file";
+    $file =~ s,/\./,/,g;
+  }
+  else
+  {
+    # Find in PATH
+    $file = which($file);
+  }
+
+  return $file;
+}
+
+##############################################################################
+#
+#  Form a command line that can handle spaces in paths and arguments
+#
+##############################################################################
+
+sub quote_options {
+  my @cmd;
+  foreach my $opt ( @_ )
+  {
+    next unless $opt;           # If undefined or empty, just skip
+    push(@cmd, "\"$opt\"");       # Quote argument
+  }
+  return join(" ", @cmd);
+}
+
+##############################################################################
+#
+#  Main program
+#
+##############################################################################
+
+my $me = get_full_path($0);
+$basedir = dirname(dirname($me)); # Remove "/bin/mysql_config" part
+
+my $ldata   = 'C:/Program Files/MySql/MySQL Server 6.0/data';
+my $execdir = 'C:/Program Files/MySql/MySQL Server 6.0/bin';
+my $bindir  = 'C:/Program Files/MySql/MySQL Server 6.0/bin';
+
+# ----------------------------------------------------------------------
+# If installed, search for the compiled in directory first (might be "lib64")
+# ----------------------------------------------------------------------
+
+my $pkglibdir = fix_path('',"libmysql/relwithdebinfo",
+                         "libmysql/release","libmysql/debug","lib/mysql","lib");
+
+my $pkgincludedir = fix_path('', "include/mysql", "include");
+
+# Assume no argument with space in it
+my @ldflags = split(" ",'');
+
+my $port;
+if ( '0' == 0 ) {
+  $port = 0;
+} else {
+  $port = '3306';
+}
+
+# ----------------------------------------------------------------------
+# Create options 
+# We intentionally add a space to the beginning and end of lib strings, simplifies replace later
+# ----------------------------------------------------------------------
+
+my (@lib_opts,@lib_r_opts,@lib_e_opts);
+if ( $^O eq "MSWin32" )
+{
+  my $linkpath   = "$pkglibdir";
+  # user32 is only needed for debug or embedded
+  my @winlibs = ("wsock32.lib","advapi32.lib","user32.lib");
+  @lib_opts   = ("$linkpath/mysqlclient.lib",@winlibs);
+  @lib_r_opts = @lib_opts;
+  @lib_e_opts = ("$linkpath/mysqlserver.lib",@winlibs);
+}
+else
+{
+  my $linkpath   = "-L$pkglibdir";
+  @lib_opts   = ($linkpath,"-lmysqlclient");
+  @lib_r_opts = ($linkpath,"-lmysqlclient_r");
+  @lib_e_opts = ($linkpath,"-lmysqld");
+}
+
+my $flags;
+$flags->{libs} =
+  [@ldflags,@lib_opts,'','','',''];
+$flags->{libs_r} =
+  [@ldflags,@lib_r_opts,'','',''];
+$flags->{embedded_libs} =
+  [@ldflags,@lib_e_opts,'','','','',''];
+
+$flags->{include} = ["-I$pkgincludedir"];
+$flags->{cflags}  = [@{$flags->{include}},split(" ",'-D_WINDOWS /MT /Zi /O2 /Ob1 /D NDEBUG -DDBUG_OFF /Op')];
+
+# ----------------------------------------------------------------------
+# Remove some options that a client doesn't have to care about
+# FIXME until we have a --cxxflags, we need to remove -Xa
+#       and -xstrconst to make --cflags usable for Sun Forte C++
+# ----------------------------------------------------------------------
+
+my $filter = join("|", @exclude_cflags);
+my @tmp = @{$flags->{cflags}};          # Copy the flag list
+$flags->{cflags} = [];                  # Clear it
+foreach my $cflag ( @tmp )
+{
+  push(@{$flags->{cflags}}, $cflag) unless $cflag =~ m/^($filter)$/o;
+}
+
+# Same for --libs(_r)
+$filter = join("|", @exclude_libs);
+foreach my $lib_type ( "libs","libs_r","embedded_libs" )
+{
+  my @tmp = @{$flags->{$lib_type}};          # Copy the flag list
+  $flags->{$lib_type} = [];                  # Clear it
+  foreach my $lib ( @tmp )
+  {
+    push(@{$flags->{$lib_type}}, $lib) unless $lib =~ m/^($filter)$/o;
+  }
+}
+
+my $include =       quote_options(@{$flags->{include}});
+my $cflags  =       quote_options(@{$flags->{cflags}});
+my $libs    =       quote_options(@{$flags->{libs}});
+my $libs_r  =       quote_options(@{$flags->{libs_r}});
+my $embedded_libs = quote_options(@{$flags->{embedded_libs}});
+
+##############################################################################
+#
+#  Usage information, output if no option is given
+#
+##############################################################################
+
+sub usage
+{
+  print <<EOF;
+Usage: $0 [OPTIONS]
+Options:
+        --cflags         [$cflags]
+        --include        [$include]
+        --libs           [$libs]
+        --libs_r         [$libs_r]
+        --socket         [$socket]
+        --port           [$port]
+        --version        [$version]
+        --libmysqld-libs [$embedded_libs]
+EOF
+  exit 1;
+}
+
+@ARGV or usage();
+
+##############################################################################
+#
+#  Get options and output the values
+#
+##############################################################################
+
+GetOptions(
+           "cflags"  => sub { print "$cflags\n" },
+           "include" => sub { print "$include\n" },
+           "libs"    => sub { print "$libs\n" },
+           "libs_r"  => sub { print "$libs_r\n" },
+           "socket"  => sub { print "$socket\n" },
+           "port"    => sub { print "$port\n" },
+           "version" => sub { print "$version\n" },
+           "embedded-libs|embedded|libmysqld-libs" =>
+             sub { print "$embedded_libs\n" },
+           ) or usage();
+
+exit 0
Thread
bk commit into 6.0 tree (jas:1.2671)U-ROWVWADEjas8 May