On 15.01.2013 00:14, Heikki Linnakangas wrote:
On 14.01.2013 23:35, Tom Lane wrote:
Since commit 2065dd2834e832eb820f1fbcd16746d6af1f6037, there have been
a few buildfarm failures along the lines of

-- Commit table drop
COMMIT PREPARED 'regress-two';
! PANIC: failed to re-find shared proclock object
! PANIC: failed to re-find shared proclock object
! connection to server was lost

Evidently I bollixed something, but what? I've been unable to reproduce
this locally so far. Anybody see what's wrong?

I was able to reproduce this by setting max_locks_per_transaction and
max_connections to the minimum. My assumption is that there's something
wrong in the way hash_update_hash_key() handles collisions.

The problem seems to be when the the old and the key hash to the same bucket. In that case, hash_update_hash_key() tries to link the entry to itself. The attached patch fixes it for me.

- Heikki
*** a/src/backend/utils/hash/dynahash.c
--- b/src/backend/utils/hash/dynahash.c
***************
*** 1022,1027 **** hash_update_hash_key(HTAB *hashp,
--- 1022,1028 ----
  	uint32		newhashvalue;
  	Size		keysize;
  	uint32		bucket;
+ 	uint32		newbucket;
  	long		segment_num;
  	long		segment_ndx;
  	HASHSEGMENT segp;
***************
*** 1078,1087 **** hash_update_hash_key(HTAB *hashp,
  	 */
  	newhashvalue = hashp->hash(newKeyPtr, hashp->keysize);
  
! 	bucket = calc_bucket(hctl, newhashvalue);
! 
! 	segment_num = bucket >> hashp->sshift;
! 	segment_ndx = MOD(bucket, hashp->ssize);
  
  	segp = hashp->dir[segment_num];
  
--- 1079,1087 ----
  	 */
  	newhashvalue = hashp->hash(newKeyPtr, hashp->keysize);
  
! 	newbucket = calc_bucket(hctl, newhashvalue);
! 	segment_num = newbucket >> hashp->sshift;
! 	segment_ndx = MOD(newbucket, hashp->ssize);
  
  	segp = hashp->dir[segment_num];
  
***************
*** 1115,1126 **** hash_update_hash_key(HTAB *hashp,
  
  	currBucket = existingElement;
  
! 	/* OK to remove record from old hash bucket's chain. */
! 	*oldPrevPtr = currBucket->link;
  
! 	/* link into new hashbucket chain */
! 	*prevBucketPtr = currBucket;
! 	currBucket->link = NULL;
  
  	/* copy new key into record */
  	currBucket->hashvalue = newhashvalue;
--- 1115,1129 ----
  
  	currBucket = existingElement;
  
! 	if (bucket != newbucket)
! 	{
! 		/* OK to remove record from old hash bucket's chain. */
! 		*oldPrevPtr = currBucket->link;
  
! 		/* link into new hashbucket chain */
! 		*prevBucketPtr = currBucket;
! 		currBucket->link = NULL;
! 	}
  
  	/* copy new key into record */
  	currBucket->hashvalue = newhashvalue;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to