/* Copyright (c) 2015 Red Hat, Inc. This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #ifndef __CHANGELOG_EV_HANDLE_H #define __CHANGELOG_EV_HANDLE_H #include #include #include "rpc-clnt.h" #include struct changelog_clnt; typedef struct changelog_rpc_clnt { xlator_t *this; gf_lock_t lock; gf_atomic_t ref; gf_boolean_t disconnected; unsigned int filter; char sock[UNIX_PATH_MAX]; struct changelog_clnt *c_clnt; /* back pointer to list holder */ struct rpc_clnt *rpc; /* RPC client endpoint */ struct list_head list; /* ->pending, ->waitq, ->active */ void (*cleanup)(struct changelog_rpc_clnt *); /* cleanup handler */ } changelog_rpc_clnt_t; static inline void changelog_rpc_clnt_ref(changelog_rpc_clnt_t *crpc) { GF_ATOMIC_INC(crpc->ref); } static inline void changelog_set_disconnect_flag(changelog_rpc_clnt_t *crpc, gf_boolean_t flag) { crpc->disconnected = flag; } static inline int changelog_rpc_clnt_is_disconnected(changelog_rpc_clnt_t *crpc) { return (crpc->disconnected == _gf_true); } static inline void changelog_rpc_clnt_unref(changelog_rpc_clnt_t *crpc) { gf_boolean_t gone = _gf_false; uint64_t ref = 0; ref = GF_ATOMIC_DEC(crpc->ref); if (!ref && changelog_rpc_clnt_is_disconnected(crpc)) { list_del(&crpc->list); gone = _gf_true; } if (gone) crpc->cleanup(crpc); } /** * This structure holds pending and active clients. On probe RPC all * an instance of the above structure (@changelog_rpc_clnt) is placed * in ->pending and gets moved to ->active on a successful connect. * * locking rules: * * Manipulating ->pending * ->pending_lock * ->pending * * Manipulating ->active * ->active_lock * ->active * * Moving object from ->pending to ->active * ->pending_lock * ->active_lock * * Objects are _never_ moved from ->active to ->pending, i.e., during * disconnection, the object is destroyed. Well, we could have tried * to reconnect, but that's pure waste.. let the other end reconnect. */ typedef struct changelog_clnt { xlator_t *this; /* pending connections */ pthread_mutex_t pending_lock; pthread_cond_t pending_cond; struct list_head pending; /* current active connections */ gf_lock_t active_lock; struct list_head active; gf_lock_t wait_lock; struct list_head waitq; /* consumer part of rot-buffs */ rbuf_t *rbuf; unsigned long sequence; } changelog_clnt_t; void * changelog_ev_connector(void *); void * changelog_ev_dispatch(void *); /* APIs */ void changelog_ev_queue_connection(changelog_clnt_t *, changelog_rpc_clnt_t *); void changelog_ev_cleanup_connections(xlator_t *, changelog_clnt_t *); void changelog_process_cleanup_event(xlator_t *); #endif