LCOV - code coverage report
Current view: top level - ovsdb - server.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 77 97.4 %
Date: 2016-09-14 01:02:56 Functions: 13 13 100.0 %
Branches: 26 36 72.2 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2011, 2012 Nicira, Inc.
       2                 :            :  *
       3                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            :  * you may not use this file except in compliance with the License.
       5                 :            :  * You may obtain a copy of the License at:
       6                 :            :  *
       7                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            :  *
       9                 :            :  * Unless required by applicable law or agreed to in writing, software
      10                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            :  * See the License for the specific language governing permissions and
      13                 :            :  * limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <config.h>
      17                 :            : 
      18                 :            : #include "server.h"
      19                 :            : 
      20                 :            : #include "hash.h"
      21                 :            : #include "ovsdb.h"
      22                 :            : 
      23                 :            : /* Initializes 'session' as a session within 'server'. */
      24                 :            : void
      25                 :       8192 : ovsdb_session_init(struct ovsdb_session *session, struct ovsdb_server *server)
      26                 :            : {
      27                 :       8192 :     session->server = server;
      28                 :       8192 :     ovs_list_init(&session->completions);
      29                 :       8192 :     hmap_init(&session->waiters);
      30                 :       8192 : }
      31                 :            : 
      32                 :            : /* Destroys 'session'. */
      33                 :            : void
      34                 :       8187 : ovsdb_session_destroy(struct ovsdb_session *session)
      35                 :            : {
      36         [ -  + ]:       8187 :     ovs_assert(hmap_is_empty(&session->waiters));
      37                 :       8187 :     hmap_destroy(&session->waiters);
      38                 :       8187 : }
      39                 :            : 
      40                 :            : /* Searches 'session' for an ovsdb_lock_waiter named 'lock_name' and returns
      41                 :            :  * it if it finds one, otherwise NULL. */
      42                 :            : struct ovsdb_lock_waiter *
      43                 :       6134 : ovsdb_session_get_lock_waiter(const struct ovsdb_session *session,
      44                 :            :                               const char *lock_name)
      45                 :            : {
      46                 :            :     struct ovsdb_lock_waiter *waiter;
      47                 :            : 
      48 [ +  + ][ -  + ]:       6134 :     HMAP_FOR_EACH_WITH_HASH (waiter, session_node, hash_string(lock_name, 0),
      49                 :            :                              &session->waiters) {
      50         [ +  - ]:       5498 :         if (!strcmp(lock_name, waiter->lock_name)) {
      51                 :       5498 :             return waiter;
      52                 :            :         }
      53                 :            :     }
      54                 :        636 :     return NULL;
      55                 :            : }
      56                 :            : 
      57                 :            : /* Returns the waiter that owns 'lock'.
      58                 :            :  *
      59                 :            :  * A lock always has an owner, so this function will never return NULL. */
      60                 :            : struct ovsdb_lock_waiter *
      61                 :       6136 : ovsdb_lock_get_owner(const struct ovsdb_lock *lock)
      62                 :            : {
      63                 :       6136 :     return CONTAINER_OF(ovs_list_front(&lock->waiters),
      64                 :            :                         struct ovsdb_lock_waiter, lock_node);
      65                 :            : }
      66                 :            : 
      67                 :            : /* Removes 'waiter' from its lock's list.  This means that, if 'waiter' was
      68                 :            :  * formerly the owner of its lock, then it no longer owns it.
      69                 :            :  *
      70                 :            :  * Returns the session that now owns 'waiter'.  This is NULL if 'waiter' was
      71                 :            :  * the lock's owner and no other sessions were waiting for the lock.  In this
      72                 :            :  * case, the lock has been destroyed, so the caller must be sure not to refer
      73                 :            :  * to it again.  A nonnull return value reflects a change in the lock's
      74                 :            :  * ownership if and only if 'waiter' formerly owned the lock. */
      75                 :            : struct ovsdb_session *
      76                 :        636 : ovsdb_lock_waiter_remove(struct ovsdb_lock_waiter *waiter)
      77                 :            : {
      78                 :        636 :     struct ovsdb_lock *lock = waiter->lock;
      79                 :            : 
      80                 :        636 :     ovs_list_remove(&waiter->lock_node);
      81                 :        636 :     waiter->lock = NULL;
      82                 :            : 
      83         [ +  + ]:        636 :     if (ovs_list_is_empty(&lock->waiters)) {
      84                 :        633 :         hmap_remove(&lock->server->locks, &lock->hmap_node);
      85                 :        633 :         free(lock->name);
      86                 :        633 :         free(lock);
      87                 :        633 :         return NULL;
      88                 :            :     }
      89                 :            : 
      90                 :          3 :     return ovsdb_lock_get_owner(lock)->session;
      91                 :            : }
      92                 :            : 
      93                 :            : /* Destroys 'waiter', which must have already been removed from its lock's
      94                 :            :  * waiting list with ovsdb_lock_waiter_remove().
      95                 :            :  *
      96                 :            :  * Removing and destroying locks are decoupled because a lock initially created
      97                 :            :  * by the "steal" request, that is later stolen by another client, remains in
      98                 :            :  * the database session until the database client sends an "unlock" request. */
      99                 :            : void
     100                 :        636 : ovsdb_lock_waiter_destroy(struct ovsdb_lock_waiter *waiter)
     101                 :            : {
     102         [ -  + ]:        636 :     ovs_assert(!waiter->lock);
     103                 :        636 :     hmap_remove(&waiter->session->waiters, &waiter->session_node);
     104                 :        636 :     free(waiter->lock_name);
     105                 :        636 :     free(waiter);
     106                 :        636 : }
     107                 :            : 
     108                 :            : /* Returns true if 'waiter' owns its associated lock. */
     109                 :            : bool
     110                 :       6132 : ovsdb_lock_waiter_is_owner(const struct ovsdb_lock_waiter *waiter)
     111                 :            : {
     112 [ +  - ][ +  + ]:       6132 :     return waiter->lock && waiter == ovsdb_lock_get_owner(waiter->lock);
     113                 :            : }
     114                 :            : 
     115                 :            : /* Initializes 'server'.
     116                 :            :  *
     117                 :            :  * The caller must call ovsdb_server_add_db() for each database to which
     118                 :            :  * 'server' should provide access. */
     119                 :            : void
     120                 :       1265 : ovsdb_server_init(struct ovsdb_server *server)
     121                 :            : {
     122                 :       1265 :     shash_init(&server->dbs);
     123                 :       1265 :     hmap_init(&server->locks);
     124                 :       1265 : }
     125                 :            : 
     126                 :            : /* Adds 'db' to the set of databases served out by 'server'.  Returns true if
     127                 :            :  * successful, false if 'db''s name is the same as some database already in
     128                 :            :  * 'server'. */
     129                 :            : bool
     130                 :       1276 : ovsdb_server_add_db(struct ovsdb_server *server, struct ovsdb *db)
     131                 :            : {
     132                 :       1276 :     return shash_add_once(&server->dbs, db->schema->name, db);
     133                 :            : }
     134                 :            : 
     135                 :            : /* Removes 'db' from the set of databases served out by 'server'.  Returns
     136                 :            :  * true if successful, false if there is no db associated with
     137                 :            :  * db->schema->name. */
     138                 :            : bool
     139                 :          2 : ovsdb_server_remove_db(struct ovsdb_server *server, struct ovsdb *db)
     140                 :            : {
     141                 :          2 :     void *data = shash_find_and_delete(&server->dbs, db->schema->name);
     142         [ +  - ]:          2 :     if (data) {
     143                 :          2 :         return true;
     144                 :            :     }
     145                 :          0 :     return false;
     146                 :            : }
     147                 :            : 
     148                 :            : /* Destroys 'server'. */
     149                 :            : void
     150                 :       1263 : ovsdb_server_destroy(struct ovsdb_server *server)
     151                 :            : {
     152                 :       1263 :     shash_destroy(&server->dbs);
     153                 :       1263 :     hmap_destroy(&server->locks);
     154                 :       1263 : }
     155                 :            : 
     156                 :            : static struct ovsdb_lock *
     157                 :        636 : ovsdb_server_create_lock__(struct ovsdb_server *server, const char *lock_name,
     158                 :            :                            uint32_t hash)
     159                 :            : {
     160                 :            :     struct ovsdb_lock *lock;
     161                 :            : 
     162 [ +  + ][ -  + ]:        636 :     HMAP_FOR_EACH_WITH_HASH (lock, hmap_node, hash, &server->locks) {
     163         [ +  - ]:          3 :         if (!strcmp(lock->name, lock_name)) {
     164                 :          3 :             return lock;
     165                 :            :         }
     166                 :            :     }
     167                 :            : 
     168                 :        633 :     lock = xzalloc(sizeof *lock);
     169                 :        633 :     lock->server = server;
     170                 :        633 :     lock->name = xstrdup(lock_name);
     171                 :        633 :     hmap_insert(&server->locks, &lock->hmap_node, hash);
     172                 :        633 :     ovs_list_init(&lock->waiters);
     173                 :            : 
     174                 :        633 :     return lock;
     175                 :            : }
     176                 :            : 
     177                 :            : /* Attempts to acquire the lock named 'lock_name' for 'session' within
     178                 :            :  * 'server'.  Returns the new lock waiter.
     179                 :            :  *
     180                 :            :  * If 'mode' is OVSDB_LOCK_STEAL, then the new lock waiter is always the owner
     181                 :            :  * of the lock.  '*victimp' receives the session of the previous owner or NULL
     182                 :            :  * if the lock was previously unowned.  (If the victim itself originally
     183                 :            :  * obtained the lock through a "steal" operation, then this function also
     184                 :            :  * removes the victim from the lock's waiting list.)
     185                 :            :  *
     186                 :            :  * If 'mode' is OVSDB_LOCK_WAIT, then the new lock waiter is the owner of the
     187                 :            :  * lock only if this lock had no existing owner.  '*victimp' is set to NULL. */
     188                 :            : struct ovsdb_lock_waiter *
     189                 :        636 : ovsdb_server_lock(struct ovsdb_server *server,
     190                 :            :                   struct ovsdb_session *session,
     191                 :            :                   const char *lock_name,
     192                 :            :                   enum ovsdb_lock_mode mode,
     193                 :            :                   struct ovsdb_session **victimp)
     194                 :            : {
     195                 :        636 :     uint32_t hash = hash_string(lock_name, 0);
     196                 :            :     struct ovsdb_lock_waiter *waiter, *victim;
     197                 :            :     struct ovsdb_lock *lock;
     198                 :            : 
     199                 :        636 :     lock = ovsdb_server_create_lock__(server, lock_name, hash);
     200         [ +  - ]:          1 :     victim = (mode == OVSDB_LOCK_STEAL && !ovs_list_is_empty(&lock->waiters)
     201                 :            :               ? ovsdb_lock_get_owner(lock)
     202         [ +  + ]:        637 :               : NULL);
     203                 :            : 
     204                 :        636 :     waiter = xmalloc(sizeof *waiter);
     205                 :        636 :     waiter->mode = mode;
     206                 :        636 :     waiter->lock_name = xstrdup(lock_name);
     207                 :        636 :     waiter->lock = lock;
     208         [ +  + ]:        636 :     if (mode == OVSDB_LOCK_STEAL) {
     209                 :          1 :         ovs_list_push_front(&lock->waiters, &waiter->lock_node);
     210                 :            :     } else {
     211                 :        635 :         ovs_list_push_back(&lock->waiters, &waiter->lock_node);
     212                 :            :     }
     213                 :        636 :     waiter->session = session;
     214                 :        636 :     hmap_insert(&waiter->session->waiters, &waiter->session_node, hash);
     215                 :            : 
     216 [ +  + ][ -  + ]:        636 :     if (victim && victim->mode == OVSDB_LOCK_STEAL) {
     217                 :          0 :         ovsdb_lock_waiter_remove(victim);
     218                 :            :     }
     219         [ +  + ]:        636 :     *victimp = victim ? victim->session : NULL;
     220                 :            : 
     221                 :        636 :     return waiter;
     222                 :            : }

Generated by: LCOV version 1.12