ctdb-server: Replace ctdb_logging.h with common/logging.h
[obnox/samba/samba-obnox.git] / ctdb / server / ctdb_serverids.c
1 /* 
2    ctdb_control protocol code to manage server ids
3
4    Copyright (C) Ronnie Sahlberg 2007
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 #include "replace.h"
20 #include "system/network.h"
21
22 #include <talloc.h>
23
24 #include "lib/util/debug.h"
25
26 #include "ctdb_private.h"
27
28 #include "common/rb_tree.h"
29 #include "common/reqid.h"
30 #include "common/common.h"
31 #include "common/logging.h"
32
33
34 #define SERVER_ID_KEY_SIZE 3
35 static uint32_t *get_server_id_key(struct ctdb_client_id *server_id)
36 {
37         static uint32_t key[SERVER_ID_KEY_SIZE];
38
39         key[0] = server_id->type;
40         key[1] = server_id->pnn;
41         key[2] = server_id->server_id;
42
43         return &key[0];
44 }
45
46 /* add a server_id to the tree.
47    if we had already 'data' in the tree then this is a duplicate and we can
48    just talloc_free the structure in parm and leave data in the tree.
49    othervise if this is a new node we return parm and that is inserted
50    into the tree.
51 */
52 static void *add_server_id_callback(void *parm, void *data)
53 {
54         if (data) {
55                 talloc_free(parm);
56                 return data;
57         }
58         return parm;
59 }
60
61 /*
62   register a server id
63   a serverid that is registered with ctdb will be automatically unregistered
64   once the client domain socket dissappears.
65  */
66 int32_t ctdb_control_register_server_id(struct ctdb_context *ctdb, 
67                                  uint32_t client_id,
68                                  TDB_DATA indata)
69 {
70         struct ctdb_client_id *server_id;
71         struct ctdb_client *client = reqid_find(ctdb->idr, client_id, struct ctdb_client);
72
73
74         if (client == NULL) {
75                 DEBUG(DEBUG_ERR,(__location__ " Could not find client parent structure. You can not send this control to a remote node\n"));
76                 return 1;
77         }
78
79         /* hang the server_id structure off client before storing it in the
80            tree so that is will be automatically destroyed when client
81            is destroyed. 
82            when the structure is free'd it will be automatically
83            removed from the tree
84         */
85         server_id = talloc_zero(client, struct ctdb_client_id);
86         CTDB_NO_MEMORY(ctdb, server_id);
87         memcpy(server_id, indata.dptr, sizeof(struct ctdb_client_id));
88
89         trbt_insertarray32_callback(ctdb->server_ids, SERVER_ID_KEY_SIZE,
90                 get_server_id_key(server_id), 
91                 add_server_id_callback, server_id);
92
93         return 0;
94 }
95
96
97 /*
98   check whether a server id exists
99  */
100 int32_t ctdb_control_check_server_id(struct ctdb_context *ctdb, 
101                                  TDB_DATA indata)
102 {
103         struct ctdb_client_id *server_id = (struct ctdb_client_id *)indata.dptr;
104
105         return trbt_lookuparray32(ctdb->server_ids, 
106                                   SERVER_ID_KEY_SIZE,
107                                   get_server_id_key(server_id)) == NULL? 0 : 1;
108 }
109
110 /*
111   unregisters a server id
112  */
113 int32_t ctdb_control_unregister_server_id(struct ctdb_context *ctdb, 
114                                  TDB_DATA indata)
115 {
116         struct ctdb_client_id *server_id = (struct ctdb_client_id *)indata.dptr;
117
118         talloc_free(trbt_lookuparray32(ctdb->server_ids, 
119                         SERVER_ID_KEY_SIZE,
120                         get_server_id_key(server_id)));
121         return 0;
122 }
123
124
125
126
127 struct count_server_ids {
128         int count;
129         struct ctdb_client_id_list_old *list;
130 };
131
132 static int server_id_count(void *param, void *data)
133 {
134         struct count_server_ids *svid = talloc_get_type(param, 
135                                                 struct count_server_ids);
136
137         if (svid == NULL) {
138                 DEBUG(DEBUG_ERR, (__location__ " Got null pointer for svid\n"));
139                 return -1;
140         }
141
142         svid->count++;
143         return 0;
144 }
145
146 static int server_id_store(void *param, void *data)
147 {
148         struct count_server_ids *svid = talloc_get_type(param, 
149                                                 struct count_server_ids);
150         struct ctdb_client_id *server_id = talloc_get_type(data,
151                                                 struct ctdb_client_id);
152
153         if (svid == NULL) {
154                 DEBUG(DEBUG_ERR, (__location__ " Got null pointer for svid\n"));
155                 return -1;
156         }
157
158         if (svid->count >= svid->list->num) {
159                 DEBUG(DEBUG_ERR, (__location__ " size of server id tree changed during traverse\n"));
160                 return -1;
161         }
162
163         memcpy(&svid->list->server_ids[svid->count], server_id, sizeof(struct ctdb_client_id));
164         svid->count++;
165         return 0;
166 }
167
168 /* 
169    returns a list of all registered server ids for a node
170 */
171 int32_t ctdb_control_get_server_id_list(struct ctdb_context *ctdb, TDB_DATA *outdata)
172 {
173         struct count_server_ids *svid;
174
175
176         svid = talloc_zero(outdata, struct count_server_ids);
177         CTDB_NO_MEMORY(ctdb, svid);
178
179
180         /* first we must count how many entries we have */
181         trbt_traversearray32(ctdb->server_ids, SERVER_ID_KEY_SIZE,
182                         server_id_count, svid);
183
184
185         outdata->dsize = offsetof(struct ctdb_client_id_list_old, server_ids)
186                         + sizeof(struct ctdb_client_id) * svid->count;
187         outdata->dptr  = talloc_size(outdata, outdata->dsize);
188         CTDB_NO_MEMORY(ctdb, outdata->dptr);
189
190
191         /* now fill the structure in */
192         svid->list = (struct ctdb_client_id_list_old *)(outdata->dptr);
193         svid->list->num = svid->count;
194         svid->count=0;
195         trbt_traversearray32(ctdb->server_ids, SERVER_ID_KEY_SIZE,
196                         server_id_store, svid);
197
198
199         return 0;
200 }