/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * syncbitvector.c
 * 		Implementation of interface for synchronized bit vectors.
 *
 * Synchronized bit vectors are stored in shared memory, so they can be accessed
 * by all backends. Synchronization is achieved by using the test-and-test-and-set
 * technique so the overhead is minimal.
 *
 * The size of each bit vector is set to BITVECTOR_SIZE_BYTES. The postmaster
 * allocates a shared memory segment that can hold up to SYNC_BITVECTOR_MAX_COUNT
 * bit vectors. This shared memory segment is passed to all backends during their
 * initialization. At shutdown the postmaster releases the shared memory segment.
 * In the occurrence of a severe failure, the postmaster resets shared memory; at
 * this point the bit vector information is lost.
 *
 */

#include "postgres.h"
#include "storage/shmem.h"
#include "utils/syncbitvector.h"
#include "utils/atomic.h"

/*
 * bit vector access descriptor.
 *
 * The bit vector is accessed using uint32 data.
 * Each datum has 32 bits. The bit is assumed to be
 * located in the (datum_offset)-th datum.
 */
typedef struct datumIdx
{
	int64 datum_offset;		/* offset of the datum inside the bit vector */

	uint32 bit_mask;		/* bit mask for the uint32 datum that contains the bit */

} datumIdx;

/* static functions */
static inline void *getVector(SyncBitvectorContainer container, int32 vectorOffset);
static inline datumIdx *getDatumIdx(uint64 offset, datumIdx *idx);

/*
 * Returns the size of the shared memory segment
 * required for holding (vectorCount) bit vectors.
 */
Size SyncBitVector_ShmemSize(int vectorCount)
{
	Assert(vectorCount <= SYNC_BITVECTOR_MAX_COUNT && "vector count exceeds maximum value");

	Size size = sizeof(SyncBitvectorContainer_s) + vectorCount * BITVECTOR_SIZE_BYTES;

	return size;
}

/*
 * Initializes the shared memory segment and casts it to a bit vector container.
 */
SyncBitvectorContainer SyncBitVector_ShmemInit(const char *name, int vectorCount)
{
	bool found = false; 	/* indicates if the shmem segment has already been initialized */
	const Size size = SyncBitVector_ShmemSize(vectorCount);

	SyncBitvectorContainer container = (SyncBitvectorContainer) ShmemInitStruct(name, size, &found);

	if (container == NULL) {
		ereport(ERROR,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 (errmsg("Not enough shared memory for SyncBitVector."))));
	}

	if (!found)
	{
		/* only the postmaster resets the bit vector container */
		MemSet(container, 0, size);
		container->vectorCount = vectorCount;
	}

	return container;
}

/*
 * Returns the bit value for the given offset inside the given vector.
 */
bool SyncBitVector_GetBit(SyncBitvectorContainer container, int32 vectorOffset, int64 bitOffset)
{
	void *vector = getVector(container, vectorOffset);

	/* use uint32 as datum type to access bit vector */
	datumIdx idx;
	getDatumIdx(bitOffset, &idx);

	uint32 *pdatum = ((uint32 *) vector) + idx.datum_offset;
	uint32 bit = (*pdatum) & idx.bit_mask;

	return (bit != 0);
}

/*
 * Sets the bit value for the given offset inside the given vector.
 * Non-synchronized operation.
 */
void SyncBitVector_SetBit(SyncBitvectorContainer container, int32 vectorOffset, int64 bitOffset)
{
	void *vector = getVector(container, vectorOffset);

	/* use uint32 as datum type to access bit vector */
	datumIdx idx;
	getDatumIdx(bitOffset, &idx);

	uint32 *pdatum = ((uint32 *) vector) + idx.datum_offset;
	*pdatum |= idx.bit_mask;
}

/*
 * Checks the bit value for the given offset inside the given vector.
 * Returns false if the bit is set, otherwise sets it and returns true.
 * Synchronized operation (through atomic test and set).
 */
bool SyncBitVector_TestTestSetBit(SyncBitvectorContainer container, int32 vectorOffset, uint64 bitOffset)
{
	void *vector = getVector(container, vectorOffset);

	/* use uint32 as datum type to access bit vector */
	datumIdx idx;
	getDatumIdx(bitOffset, &idx);

	/*
	 * We use TestTestSet on a 32-bit datum. This fails if any of the datum
	 * bits are changed, i.e. if a concurrent update changes a different bit
	 * than the one we want to set. We therefore need to recheck the bit and,
	 * if it is not set, call compare_and_swap again.
	 */
	int32 i = 0;
	for (i = 0; i < 32; i++)	/* 32-bit datum */
	{
		bool swapped = false;
		uint32 *pdatum = ((uint32 *) vector) + idx.datum_offset;
		uint32 bit = (*pdatum) & idx.bit_mask;
		uint32 datumOld = *pdatum;
		uint32 datumNew = datumOld | idx.bit_mask;

		/* test */
		if (bit)
		{
			return false;
		}

		/* test and set */
		swapped = compare_and_swap_32(pdatum, datumOld, datumNew);
		if (swapped)
		{
			return true;
		}
	}

	return false;
}

/*
 * Returns the base pointer for a bit vector given its offset.
 */
static inline
void *getVector(SyncBitvectorContainer container, int32 vectorOffset)
{
	Assert(container);
	Assert(container->base);
	Assert(vectorOffset >= 0 && "vector ID is negative");
	Assert(vectorOffset < container->vectorCount && "vector ID is greater than vector count");

	/* use byte arithmetics */
	int8 *base = (int8 *) container->base;
	int8 *vectorBase = base + vectorOffset * BITVECTOR_SIZE_BYTES;

	return (void *) vectorBase;
}

/*
 * Updates and returns an access descriptor for the given bit offset.
 * The offset is normalized to the bit vector size. The access descriptor
 * is allocated by the caller and passed as an argument.
 */
static inline
datumIdx *getDatumIdx(uint64 offset, datumIdx *idx)
{
	Assert(idx &&  "idx is NULL");

	/* datum size (uint32) is 32 bits */
	const int32 LogBitsPerDatum = 5; 					/* = log2(32) */
	const uint64 MaxBitValue = 31UL;

	/* offset = offset % BITVECTOR_SIZE_BITS - prevents overflow */
	offset = offset & BITVECTOR_OFFSET_MASK;

	idx->datum_offset = offset >> LogBitsPerDatum;		/* = (offset / 32) */
	idx->bit_mask = 1UL << (offset & MaxBitValue);		/* = 1 << (offset % 32) */

	return idx;
}

// EOF
