#ifndef __tailq_hash__
#define __tailq_hash__

/* Must be powers of 2 */
#define MAX_HASH_ENTRIES 128
#define SEQ_BUCKET_SIZE 262144
/*
 * The max seq range that can be stored is
 * 64 x 262144 or 16Meg. We have one extra slot
 * for fall-over but must keep it so we never have
 * wrap in hashing over valid other entries.
 */
#define MAX_ALLOWED_SEQ_RANGE (SEQ_BUCKET_SIZE * (MAX_HASH_ENTRIES-1))

struct tailq_hash {
	uint32_t min;
	uint32_t max;
	uint32_t count;
	struct rack_sendmap *rsm_min;
	struct rack_sendmap *rsm_max;
	struct rack_head ht[MAX_HASH_ENTRIES];
};

struct rack_sendmap *
tqhash_min(struct tailq_hash *hs);

struct rack_sendmap *
tqhash_max(struct tailq_hash *hs);

int
tqhash_empty(struct tailq_hash *hs);

struct rack_sendmap *
tqhash_find(struct tailq_hash *hs, uint32_t seq);

struct rack_sendmap *
tqhash_next(struct tailq_hash *hs, struct rack_sendmap *rsm);

struct rack_sendmap *
tqhash_prev(struct tailq_hash *hs, struct rack_sendmap *rsm);

#define REMOVE_TYPE_CUMACK	1	/* Cumack moved */
#define REMOVE_TYPE_MERGE	2	/* Merging two blocks */
#define REMOVE_TYPE_FINI	3	/* The connection is over */

void
tqhash_remove(struct tailq_hash *hs, struct rack_sendmap *rsm, int type);

int
tqhash_insert(struct tailq_hash *hs, struct rack_sendmap *rsm);

void
tqhash_init(struct tailq_hash *hs);

int
tqhash_trim(struct tailq_hash *hs, uint32_t th_ack);

void
tqhash_update_end(struct tailq_hash *hs, struct rack_sendmap *rsm,
    uint32_t th_ack);


#define	TQHASH_FOREACH(var, head) \
	for ((var) = tqhash_min((head));		\
	     (var);					\
	     (var) = tqhash_next((head), (var)))

#define TQHASH_FOREACH_FROM(var, head, fvar)					\
	for ((var) = ((fvar) ? (fvar) : tqhash_min((head)));		\
	    (var);							\
	     (var) = tqhash_next((head), (var)))

#define	TQHASH_FOREACH_REVERSE_FROM(var, head)		\
	for ((var) = ((var) ? (var) : tqhash_max((head)));		\
	    (var);							\
	    (var) = tqhash_prev((head), (var)))


#endif
