s3: Implement global locks in a g_lock tdb
[Samba/kamenim.git] / source3 / utils / net_g_lock.c
blobf30ed331be8497c200fe563b63e4c4d21b97d7e9
1 /*
2 * Samba Unix/Linux SMB client library
3 * Interface to the g_lock facility
4 * Copyright (C) Volker Lendecke 2009
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.
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.
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/>.
20 #include "includes.h"
21 #include "net.h"
22 #include "g_lock.h"
24 static bool net_g_lock_init(TALLOC_CTX *mem_ctx,
25 struct tevent_context **pev,
26 struct messaging_context **pmsg,
27 struct g_lock_ctx **pg_ctx)
29 struct tevent_context *ev = NULL;
30 struct messaging_context *msg = NULL;
31 struct g_lock_ctx *g_ctx = NULL;
33 ev = tevent_context_init(talloc_tos());
34 if (ev == NULL) {
35 d_fprintf(stderr, "ERROR: could not init event context\n");
36 goto fail;
38 msg = messaging_init(talloc_tos(), server_id_self(), ev);
39 if (msg == NULL) {
40 d_fprintf(stderr, "ERROR: could not init messaging context\n");
41 goto fail;
43 g_ctx = g_lock_ctx_init(talloc_tos(), msg);
44 if (g_ctx == NULL) {
45 d_fprintf(stderr, "ERROR: could not init g_lock context\n");
46 goto fail;
49 *pev = ev;
50 *pmsg = msg;
51 *pg_ctx = g_ctx;
52 return true;
53 fail:
54 TALLOC_FREE(g_ctx);
55 TALLOC_FREE(msg);
56 TALLOC_FREE(ev);
57 return false;
61 static int net_g_lock_do(struct net_context *c, int argc, const char **argv)
63 struct tevent_context *ev = NULL;
64 struct messaging_context *msg = NULL;
65 struct g_lock_ctx *g_ctx = NULL;
66 const char *name, *cmd;
67 int timeout, res;
68 bool locked = false;
69 NTSTATUS status;
70 int ret = -1;
72 if (argc != 3) {
73 d_printf("Usage: net g_lock do <lockname> <timeout> "
74 "<command>\n");
75 return -1;
77 name = argv[0];
78 timeout = atoi(argv[1]);
79 cmd = argv[2];
81 if (!net_g_lock_init(talloc_tos(), &ev, &msg, &g_ctx)) {
82 goto done;
85 status = g_lock_lock(g_ctx, name, G_LOCK_WRITE,
86 timeval_set(timeout / 1000, timeout % 1000));
87 if (!NT_STATUS_IS_OK(status)) {
88 d_fprintf(stderr, "ERROR: Could not get lock: %s\n",
89 nt_errstr(status));
90 goto done;
92 locked = true;
94 res = system(cmd);
96 if (res == -1) {
97 d_fprintf(stderr, "ERROR: system() returned %s\n",
98 strerror(errno));
99 goto done;
101 d_fprintf(stderr, "command returned %d\n", res);
103 ret = 0;
105 done:
106 if (locked) {
107 g_lock_unlock(g_ctx, name);
109 TALLOC_FREE(g_ctx);
110 TALLOC_FREE(msg);
111 TALLOC_FREE(ev);
112 return ret;
115 static int net_g_lock_dump_fn(struct server_id pid, enum g_lock_type lock_type,
116 void *private_data)
118 char *pidstr;
120 pidstr = procid_str(talloc_tos(), &pid);
121 d_printf("%s: %s (%s)\n", pidstr,
122 (lock_type & 1) ? "WRITE" : "READ",
123 (lock_type & G_LOCK_PENDING) ? "pending" : "holder");
124 TALLOC_FREE(pidstr);
125 return 0;
128 static int net_g_lock_dump(struct net_context *c, int argc, const char **argv)
130 struct tevent_context *ev = NULL;
131 struct messaging_context *msg = NULL;
132 struct g_lock_ctx *g_ctx = NULL;
133 NTSTATUS status;
134 int ret = -1;
136 if (argc != 1) {
137 d_printf("Usage: net g_lock dump <lockname>\n");
138 return -1;
141 if (!net_g_lock_init(talloc_tos(), &ev, &msg, &g_ctx)) {
142 goto done;
145 status = g_lock_dump(g_ctx, argv[0], net_g_lock_dump_fn, NULL);
147 ret = 0;
148 done:
149 TALLOC_FREE(g_ctx);
150 TALLOC_FREE(msg);
151 TALLOC_FREE(ev);
152 return ret;
155 static int net_g_lock_locks_fn(const char *name, void *private_data)
157 d_printf("%s\n", name);
158 return 0;
161 static int net_g_lock_locks(struct net_context *c, int argc, const char **argv)
163 struct tevent_context *ev = NULL;
164 struct messaging_context *msg = NULL;
165 struct g_lock_ctx *g_ctx = NULL;
166 int ret = -1;
168 if (argc != 0) {
169 d_printf("Usage: net g_lock locks\n");
170 return -1;
173 if (!net_g_lock_init(talloc_tos(), &ev, &msg, &g_ctx)) {
174 goto done;
177 ret = g_lock_locks(g_ctx, net_g_lock_locks_fn, NULL);
178 done:
179 TALLOC_FREE(g_ctx);
180 TALLOC_FREE(msg);
181 TALLOC_FREE(ev);
182 return ret;
185 int net_g_lock(struct net_context *c, int argc, const char **argv)
187 struct functable func[] = {
189 "do",
190 net_g_lock_do,
191 NET_TRANSPORT_LOCAL,
192 N_("Execute a shell command under a lock"),
193 N_("net g_lock do <lock name> <timeout> <command>\n")
196 "locks",
197 net_g_lock_locks,
198 NET_TRANSPORT_LOCAL,
199 N_("List all locknames"),
200 N_("net g_lock locks\n")
203 "dump",
204 net_g_lock_dump,
205 NET_TRANSPORT_LOCAL,
206 N_("Dump a g_lock locking table"),
207 N_("net g_lock dump <lock name>\n")
209 {NULL, NULL, 0, NULL, NULL}
212 return net_run_function(c, argc, argv, "net g_lock", func);