lib: Add lib/util/server_id.h
[kai/samba-autobuild/.git] / source3 / lib / server_id_db_util.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Utils around server_id_db with more dependencies
4  * Copyright (C) Volker Lendecke 2014
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "replace.h"
21 #include "server_id_db_util.h"
22 #include "lib/util/server_id.h"
23 #include "serverid.h"
24 #include "lib/util/samba_util.h"
25
26 static int server_id_db_check_exclusive(
27         struct server_id_db *db, const char *name,
28         unsigned num_servers, struct server_id *servers);
29
30 int server_id_db_set_exclusive(struct server_id_db *db, const char *name)
31 {
32         int ret;
33         unsigned num_servers;
34         struct server_id *servers;
35
36         ret = server_id_db_add(db, name);
37         if (ret != 0) {
38                 return ret;
39         }
40
41         ret = server_id_db_lookup(db, name, talloc_tos(),
42                                   &num_servers, &servers);
43         if (ret != 0) {
44                 goto done;
45         }
46
47         /*
48          * Remove entries from the server_id_db for processes that have died
49          * and could not clean up. This is racy, as two processes could
50          * simultaneously try to register a name. Both would succeed in the
51          * server_id_db_add call, and both would see their peer active during
52          * the check_exclusive call. Both would get an EEXIST, and nobody
53          * would be able to register itself. But this is okay, as this is
54          * meant to be a cleanup routine, and normally only one daemon should
55          * start up at a time anyway. Getting this "right" would mean we would
56          * have to add locking to server_id_db, or add a dependency on
57          * serverids_exist to server_id_db. Both are too heavy-weight for my
58          * taste.
59          */
60
61         ret = server_id_db_check_exclusive(db, name, num_servers, servers);
62         TALLOC_FREE(servers);
63
64 done:
65         if (ret != 0) {
66                 server_id_db_remove(db, name);
67         }
68         return ret;
69 }
70
71 static int server_id_db_check_exclusive(
72         struct server_id_db *db, const char *name,
73         unsigned num_servers, struct server_id *servers)
74 {
75         struct server_id me = server_id_db_pid(db);
76         unsigned i;
77
78         for (i=0; i<num_servers; i++) {
79                 int ret;
80
81                 if (server_id_same_process(&me, &servers[i])) {
82                         /*
83                          * I am always around ... :-)
84                          */
85                         continue;
86                 }
87
88                 if (serverid_exists(&servers[i])) {
89                         return EEXIST;
90                 }
91
92                 ret = server_id_db_prune_name(db, name, servers[i]);
93                 if (ret != 0) {
94                         return ret;
95                 }
96         }
97
98         return 0;
99 }