]> rtime.felk.cvut.cz Git - frescor/forb.git/blobdiff - src/discovery.c
Discovery handling moved to discovery.c
[frescor/forb.git] / src / discovery.c
index b56dd8b487b1cc563f9d38d59ea4aab6570de851..cc859906278e3215b93f83bbb5a684ca312de45c 100644 (file)
 /* covered by the GNU Public License.                                    */
 /**************************************************************************/
 
+/**
+ * @file   discovery.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Wed May 27 19:28:30 2009
+ * 
+ * @brief  Discovery functions
+ * 
+ */
+
 #include "discovery.h"
 #include <ul_log.h>
 #include "object.h"
 
 extern UL_LOG_CUST(ulogd_forb_discovery);
 
+GAVL_CUST_NODE_INT_DEC(forb_peer_nolock,/* cust_prefix */
+                      forb_t,          /* cust_root_t */
+                      forb_peer_t,     /* cust_item_t */
+                      forb_server_id,  /* cust_key_t */
+                      peers,           /* cust_root_node */
+                      gnode,           /* cust_item_node */
+                      server_id,       /* cust_item_key */
+                      forb_server_id_cmp)/* cust_cmp_fnc */
+
+GAVL_CUST_NODE_INT_IMP(forb_peer_nolock,/* cust_prefix */
+                      forb_t,          /* cust_root_t */
+                      forb_peer_t,     /* cust_item_t */
+                      forb_server_id,  /* cust_key_t */
+                      peers,           /* cust_root_node */
+                      gnode,           /* cust_item_node */
+                      server_id,       /* cust_item_key */
+                      forb_server_id_cmp);/* cust_cmp_fnc */
+
+int forb_discovery_init(forb_t *forb)
+{
+       if (fosa_mutex_init(&forb->peer_mutex, 0) != 0) return -1;
+       forb_peer_nolock_init_root_field(forb);
+
+       if (fosa_mutex_init(&forb->objkey_mutex, 0) != 0) return -1;
+       forb_objects_nolock_init_root_field(forb);
+       return 0;
+}
+
+static inline void
+forb_peer_insert(forb_t *forb, forb_peer_t *peer)
+{
+       fosa_mutex_lock(&forb->peer_mutex);
+       forb_peer_get(peer);
+       forb_peer_nolock_insert(forb, peer);
+       fosa_mutex_unlock(&forb->peer_mutex);
+}
+
+static inline void
+forb_peer_delete(forb_t *forb, forb_peer_t *peer)
+{
+       fosa_mutex_lock(&forb->peer_mutex);
+       forb_peer_nolock_delete(forb, peer);
+       forb_peer_put(peer);
+       fosa_mutex_unlock(&forb->peer_mutex);
+}
+
+/** 
+ * Finds peer with given @a server_id.
+ * 
+ * @param forb 
+ * @param server_id 
+ * 
+ * @return The found peer or NULL if no peer is found. You have to
+ * call forb_peer_put() after you finish working with the non NULL
+ * retuned value.
+ */
+forb_peer_t *
+forb_peer_find(forb_t *forb, forb_server_id *server_id)
+{
+       forb_peer_t *ret;
+       fosa_mutex_lock(&forb->peer_mutex);
+       ret = forb_peer_nolock_find(forb, server_id);
+       if (ret) {
+               forb_peer_get(ret);
+       }
+       fosa_mutex_unlock(&forb->peer_mutex);
+       return ret;
+}
+
+/** 
+ * Finds the peer with given @a server_id. If the peer is not
+ * currently known (not yet discovered or not available), this
+ * function waits at maximum @a timeout for the peer to be discovered.
+ * 
+ * @param forb 
+ * @param server_id 
+ * @param timeout 
+ * 
+ * @return The peer structure or NULL if the peer is not known even
+ * after the timeout elapses.
+ * 
+ * @note After the returned peer is not needed, forb_peer_put() must
+ * called on it.
+ */
+forb_peer_t *
+forb_peer_find_timed(forb_t *forb, forb_server_id *server_id,
+                    fosa_abs_time_t *timeout)
+{
+       forb_peer_t *peer;
+       bool peer_allocated = false;
+       
+       fosa_mutex_lock(&forb->peer_mutex);
+       peer = forb_peer_nolock_find(forb, server_id);
+       if (!peer && !timeout) goto unlock;
+       if (peer) {
+               forb_peer_get(peer);
+       } else {
+               /* We are the first who want to contact this peer */
+               peer = forb_peer_new();
+               if (!peer) goto unlock;
+               peer->server_id = *server_id;
+               peer->state = FORB_PEER_WANTED;
+               forb_peer_nolock_insert(forb, forb_peer_get(peer));
+               peer_allocated = true;
+       }
+       while (peer->state == FORB_PEER_WANTED) {
+               int ret;
+               /* Wait for the peer to be discovered. */
+               ret = fosa_cond_timedwait(&peer->cond,
+                                         &forb->peer_mutex,
+                                         timeout);
+               if (ret == FOSA_ETIMEDOUT) {
+                       /* No peer discovered within timeout */
+                       if (peer_allocated) {
+                               forb_peer_nolock_delete(forb, peer);
+                               forb_peer_put(peer);
+                       }
+                       forb_peer_put(peer);
+                       peer = NULL;
+                       break;
+               }
+       }
+unlock:        
+       fosa_mutex_unlock(&forb->peer_mutex);
+
+       return peer;
+}
+
+/** 
+ * 
+ * @param port 
+ * @param peer 
+ * @param server_id 
+ * @param addr 
+ * @param orb_id
+ * 
+ * @warning This function has to be called either from receiver thread
+ * of when the recevier thread is not running.
+ */
 void forb_new_peer_discovered(forb_port_t *port, forb_peer_t *peer,
                         forb_server_id server_id, void *addr,
                         CORBA_string orb_id)
@@ -93,3 +241,19 @@ void forb_new_peer_discovered(forb_port_t *port, forb_peer_t *peer,
        /* Broadcast our hello packet now */
        forb_syncobj_signal(&port->hello);
 }
+
+/** 
+ * 
+ * 
+ * @param peer 
+ *
+ * @warning This function has to be called either from receiver thread
+ * of when the recevier thread is not running.
+ */
+void forb_peer_disconnected(forb_peer_t *peer)
+{
+       forb_peer_delete(peer->port->forb, peer);
+       forb_port_peer_delete(peer->port, peer);
+       forb_peer_put(peer);    /* This should release the peer and in case on proto_inet close the socker. */
+}
+