diff options
Diffstat (limited to 'libglusterfs/src/stack.h')
| -rw-r--r-- | libglusterfs/src/stack.h | 266 | 
1 files changed, 266 insertions, 0 deletions
diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h new file mode 100644 index 00000000000..f014a4a27ac --- /dev/null +++ b/libglusterfs/src/stack.h @@ -0,0 +1,266 @@ +/* +  Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> +  This file is part of GlusterFS. + +  GlusterFS 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; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS 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, see +  <http://www.gnu.org/licenses/>. +*/ + +/* +  This file defines MACROS and static inlines used to emulate a function +  call over asynchronous communication with remote server +*/ + +#ifndef _STACK_H +#define _STACK_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +struct _call_stack_t; +typedef struct _call_stack_t call_stack_t; +struct _call_frame_t; +typedef struct _call_frame_t call_frame_t; +struct _call_pool_t; +typedef struct _call_pool_t call_pool_t; + +#include "xlator.h" +#include "dict.h" +#include "list.h" +#include "common-utils.h" + + +typedef int32_t (*ret_fn_t) (call_frame_t *frame, +			     call_frame_t *prev_frame, +			     xlator_t *this, +			     int32_t op_ret, +			     int32_t op_errno, +			     ...); + +struct _call_pool_t { +	union { +		struct list_head   all_frames; +		struct { +			call_stack_t *next_call; +			call_stack_t *prev_call; +		} all_stacks; +	}; +	int64_t                     cnt; +	gf_lock_t                   lock; +}; + +struct _call_frame_t { +	call_stack_t *root;        /* stack root */ +	call_frame_t *parent;      /* previous BP */ +	call_frame_t *next; +	call_frame_t *prev;        /* maintainence list */ +	void         *local;       /* local variables */ +	xlator_t     *this;        /* implicit object */ +	ret_fn_t      ret;         /* op_return address */ +	int32_t       ref_count; +	gf_lock_t     lock; +	void         *cookie;      /* unique cookie */ +}; + +struct _call_stack_t { +	union { +		struct list_head      all_frames; +		struct { +			call_stack_t *next_call; +			call_stack_t *prev_call; +		}; +	}; +	call_pool_t                  *pool; +	void                         *trans; +	uint64_t                      unique; +	void                         *state;  /* pointer to request state */ +	uid_t                         uid; +	gid_t                         gid; +	pid_t                         pid; +	call_frame_t                  frames; +	dict_t                       *req_refs; +	dict_t                       *rsp_refs; + +	int32_t                       op; +	int8_t                        type; +}; + + +static inline void +FRAME_DESTROY (call_frame_t *frame) +{ +	if (frame->next) +		frame->next->prev = frame->prev; +	if (frame->prev) +		frame->prev->next = frame->next; +	if (frame->local) +		FREE (frame->local); +	LOCK_DESTROY (&frame->lock); +	FREE (frame); +} + + +static inline void +STACK_DESTROY (call_stack_t *stack) +{ +	LOCK (&stack->pool->lock); +	{ +		list_del_init (&stack->all_frames); +		stack->pool->cnt--; +	} +	UNLOCK (&stack->pool->lock); + +	if (stack->frames.local) +		FREE (stack->frames.local); + +	LOCK_DESTROY (&stack->frames.lock); + +	while (stack->frames.next) { +		FRAME_DESTROY (stack->frames.next); +	} +	FREE (stack); +} + + +#define cbk(x) cbk_##x + + +/* make a call */ +#define STACK_WIND(frame, rfn, obj, fn, params ...)			\ +	do {								\ +		call_frame_t *_new = NULL;				\ +		                                                        \ +                _new = CALLOC (1, sizeof (call_frame_t));	        \ +		ERR_ABORT (_new);					\ +		typeof(fn##_cbk) tmp_cbk = rfn;				\ +		_new->root = frame->root;				\ +		_new->next = frame->root->frames.next;			\ +		_new->prev = &frame->root->frames;			\ +		if (frame->root->frames.next)				\ +			frame->root->frames.next->prev = _new;		\ +		frame->root->frames.next = _new;			\ +		_new->this = obj;					\ +		_new->ret = (ret_fn_t) tmp_cbk;				\ +		_new->parent = frame;					\ +		_new->cookie = _new;					\ +		LOCK_INIT (&_new->lock);				\ +		frame->ref_count++;					\ +									\ +		fn (_new, obj, params);					\ +	} while (0) + + +/* make a call with a cookie */ +#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn, params ...)		\ +	do {								\ +		call_frame_t *_new = CALLOC (1,				\ +					     sizeof (call_frame_t));	\ +		ERR_ABORT (_new);					\ +		typeof(fn##_cbk) tmp_cbk = rfn;				\ +		_new->root = frame->root;				\ +		_new->next = frame->root->frames.next;			\ +		_new->prev = &frame->root->frames;			\ +		if (frame->root->frames.next)				\ +			frame->root->frames.next->prev = _new;		\ +		frame->root->frames.next = _new;			\ +		_new->this = obj;					\ +		_new->ret = (ret_fn_t) tmp_cbk;				\ +		_new->parent = frame;					\ +		_new->cookie = cky;					\ +		LOCK_INIT (&_new->lock);				\ +		frame->ref_count++;					\ +		fn##_cbk = rfn;						\ +									\ +		fn (_new, obj, params);					\ +	} while (0) + + +/* return from function */ +#define STACK_UNWIND(frame, params ...)					\ +	do {								\ +		ret_fn_t fn = frame->ret;				\ +		call_frame_t *_parent = frame->parent;			\ +		_parent->ref_count--;					\ +		fn (_parent, frame->cookie, _parent->this, params);	\ +	} while (0) + + +static inline call_frame_t * +copy_frame (call_frame_t *frame) +{ +	call_stack_t *newstack = NULL; +	call_stack_t *oldstack = NULL; + +	if (!frame) { +		return NULL; +	} + +	newstack = (void *) CALLOC (1, sizeof (*newstack)); +	oldstack = frame->root; + +	newstack->uid = oldstack->uid; +	newstack->gid = oldstack->gid; +	newstack->pid = oldstack->pid; +	newstack->unique = oldstack->unique; + +	newstack->frames.this = frame->this; +	newstack->frames.root = newstack; +	newstack->pool = oldstack->pool; + +	LOCK_INIT (&newstack->frames.lock); + +	LOCK (&oldstack->pool->lock); +	{ +		list_add (&newstack->all_frames, &oldstack->all_frames); +		newstack->pool->cnt++; +		 +	} +	UNLOCK (&oldstack->pool->lock); + +	return &newstack->frames; +} + +static inline call_frame_t * +create_frame (xlator_t *xl, call_pool_t *pool) +{ +	call_stack_t *stack = NULL; + +	if (!xl || !pool) { +		return NULL; +	} + +	stack = CALLOC (1, sizeof (*stack)); +	if (!stack) +		return NULL; + +	stack->pool = pool; +	stack->frames.root = stack; +	stack->frames.this = xl; + +	LOCK (&pool->lock); +	{ +		list_add (&stack->all_frames, &pool->all_frames); +		pool->cnt++; +	} +	UNLOCK (&pool->lock); + +	LOCK_INIT (&stack->frames.lock); + +	return &stack->frames; +} + + +#endif /* _STACK_H */  | 
