83d5d78fa6ec32f2ae368e6eeb9e95487ae195c4
[samba.git] / ctdb / protocol / protocol_types.c
1 /*
2    CTDB protocol marshalling
3
4    Copyright (C) Amitay Isaacs  2015-2017
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 "system/network.h"
22
23 #include <talloc.h>
24 #include <tdb.h>
25
26 #include "protocol.h"
27 #include "protocol_private.h"
28 #include "protocol_api.h"
29
30 size_t ctdb_tdb_data_len(TDB_DATA *in)
31 {
32         return in->dsize > UINT32_MAX ? UINT32_MAX : in->dsize;
33 }
34
35 void ctdb_tdb_data_push(TDB_DATA *in, uint8_t *buf, size_t *npush)
36 {
37         size_t len = ctdb_tdb_data_len(in);
38
39         if (len > 0) {
40                 memcpy(buf, in->dptr, len);
41         }
42
43         *npush = len;
44 }
45
46 int ctdb_tdb_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
47                        TDB_DATA *out, size_t *npull)
48 {
49         TDB_DATA val;
50
51         if (buflen > UINT32_MAX) {
52                 return EMSGSIZE;
53         }
54
55         val.dsize = buflen;
56         if (val.dsize > 0) {
57                 val.dptr = talloc_memdup(mem_ctx, buf, buflen);
58                 if (val.dptr == NULL) {
59                         return ENOMEM;
60                 }
61         } else {
62                 val.dptr = NULL;
63         }
64
65         *out = val;
66         *npull = buflen;
67         return 0;
68 }
69
70 size_t ctdb_tdb_datan_len(TDB_DATA *in)
71 {
72         uint32_t u32 = ctdb_tdb_data_len(in);
73
74         return ctdb_uint32_len(&u32) + u32;
75 }
76
77 void ctdb_tdb_datan_push(TDB_DATA *in, uint8_t *buf, size_t *npush)
78 {
79         size_t offset = 0, np;
80         uint32_t u32 = ctdb_tdb_data_len(in);
81
82         ctdb_uint32_push(&u32, buf+offset, &np);
83         offset += np;
84
85         ctdb_tdb_data_push(in, buf+offset, &np);
86         offset += np;
87
88         *npush = offset;
89 }
90
91 int ctdb_tdb_datan_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
92                         TDB_DATA *out, size_t *npull)
93 {
94         size_t offset = 0, np;
95         uint32_t u32;
96         int ret;
97
98         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
99         if (ret != 0) {
100                 return ret;
101         }
102         offset += np;
103
104         if (buflen-offset < u32) {
105                 return EMSGSIZE;
106         }
107
108         ret = ctdb_tdb_data_pull(buf+offset, u32, mem_ctx, out, &np);
109         if (ret != 0) {
110                 return ret;
111         }
112         offset += np;
113
114         *npull = offset;
115         return 0;
116 }
117
118 size_t ctdb_latency_counter_len(struct ctdb_latency_counter *in)
119 {
120         return ctdb_int32_len(&in->num) +
121                 ctdb_padding_len(4) +
122                 ctdb_double_len(&in->min) +
123                 ctdb_double_len(&in->max) +
124                 ctdb_double_len(&in->total);
125 }
126
127 void ctdb_latency_counter_push(struct ctdb_latency_counter *in, uint8_t *buf,
128                                size_t *npush)
129 {
130         size_t offset = 0, np;
131
132         ctdb_int32_push(&in->num, buf+offset, &np);
133         offset += np;
134
135         ctdb_padding_push(4, buf+offset, &np);
136         offset += np;
137
138         ctdb_double_push(&in->min, buf+offset, &np);
139         offset += np;
140
141         ctdb_double_push(&in->max, buf+offset, &np);
142         offset += np;
143
144         ctdb_double_push(&in->total, buf+offset, &np);
145         offset += np;
146
147         *npush = offset;
148 }
149
150 int ctdb_latency_counter_pull(uint8_t *buf, size_t buflen,
151                               struct ctdb_latency_counter *out, size_t *npull)
152 {
153         size_t offset = 0, np;
154         int ret;
155
156         ret = ctdb_int32_pull(buf+offset, buflen-offset, &out->num, &np);
157         if (ret != 0) {
158                 return ret;
159         }
160         offset += np;
161
162         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
163         if (ret != 0) {
164                 return ret;
165         }
166         offset += np;
167
168         ret = ctdb_double_pull(buf+offset, buflen-offset, &out->min, &np);
169         if (ret != 0) {
170                 return ret;
171         }
172         offset += np;
173
174         ret = ctdb_double_pull(buf+offset, buflen-offset, &out->max, &np);
175         if (ret != 0) {
176                 return ret;
177         }
178         offset += np;
179
180         ret = ctdb_double_pull(buf+offset, buflen-offset, &out->total, &np);
181         if (ret != 0) {
182                 return ret;
183         }
184         offset += np;
185
186         *npull = offset;
187         return 0;
188 }
189
190 size_t ctdb_statistics_len(struct ctdb_statistics *in)
191 {
192         return ctdb_uint32_len(&in->num_clients) +
193                 ctdb_uint32_len(&in->frozen) +
194                 ctdb_uint32_len(&in->recovering) +
195                 ctdb_uint32_len(&in->client_packets_sent) +
196                 ctdb_uint32_len(&in->client_packets_recv) +
197                 ctdb_uint32_len(&in->node_packets_sent) +
198                 ctdb_uint32_len(&in->node_packets_recv) +
199                 ctdb_uint32_len(&in->keepalive_packets_sent) +
200                 ctdb_uint32_len(&in->keepalive_packets_recv) +
201                 ctdb_uint32_len(&in->node.req_call) +
202                 ctdb_uint32_len(&in->node.reply_call) +
203                 ctdb_uint32_len(&in->node.req_dmaster) +
204                 ctdb_uint32_len(&in->node.reply_dmaster) +
205                 ctdb_uint32_len(&in->node.reply_error) +
206                 ctdb_uint32_len(&in->node.req_message) +
207                 ctdb_uint32_len(&in->node.req_control) +
208                 ctdb_uint32_len(&in->node.reply_control) +
209                 ctdb_uint32_len(&in->client.req_call) +
210                 ctdb_uint32_len(&in->client.req_message) +
211                 ctdb_uint32_len(&in->client.req_control) +
212                 ctdb_uint32_len(&in->timeouts.call) +
213                 ctdb_uint32_len(&in->timeouts.control) +
214                 ctdb_uint32_len(&in->timeouts.traverse) +
215                 ctdb_padding_len(4) +
216                 ctdb_latency_counter_len(&in->reclock.ctdbd) +
217                 ctdb_latency_counter_len(&in->reclock.recd) +
218                 ctdb_uint32_len(&in->locks.num_calls) +
219                 ctdb_uint32_len(&in->locks.num_current) +
220                 ctdb_uint32_len(&in->locks.num_pending) +
221                 ctdb_uint32_len(&in->locks.num_failed) +
222                 ctdb_latency_counter_len(&in->locks.latency) +
223                 MAX_COUNT_BUCKETS * ctdb_uint32_len(&in->locks.buckets[0]) +
224                 ctdb_uint32_len(&in->total_calls) +
225                 ctdb_uint32_len(&in->pending_calls) +
226                 ctdb_uint32_len(&in->childwrite_calls) +
227                 ctdb_uint32_len(&in->pending_childwrite_calls) +
228                 ctdb_uint32_len(&in->memory_used) +
229                 ctdb_uint32_len(&in->__last_counter) +
230                 ctdb_uint32_len(&in->max_hop_count) +
231                 MAX_COUNT_BUCKETS *
232                         ctdb_uint32_len(&in->hop_count_bucket[0]) +
233                 ctdb_padding_len(4) +
234                 ctdb_latency_counter_len(&in->call_latency) +
235                 ctdb_latency_counter_len(&in->childwrite_latency) +
236                 ctdb_uint32_len(&in->num_recoveries) +
237                 ctdb_padding_len(4) +
238                 ctdb_timeval_len(&in->statistics_start_time) +
239                 ctdb_timeval_len(&in->statistics_current_time) +
240                 ctdb_uint32_len(&in->total_ro_delegations) +
241                 ctdb_uint32_len(&in->total_ro_revokes);
242 }
243
244 void ctdb_statistics_push(struct ctdb_statistics *in, uint8_t *buf,
245                           size_t *npush)
246 {
247         size_t offset = 0, np;
248         int i;
249
250         ctdb_uint32_push(&in->num_clients, buf+offset, &np);
251         offset += np;
252
253         ctdb_uint32_push(&in->frozen, buf+offset, &np);
254         offset += np;
255
256         ctdb_uint32_push(&in->recovering, buf+offset, &np);
257         offset += np;
258
259         ctdb_uint32_push(&in->client_packets_sent, buf+offset, &np);
260         offset += np;
261
262         ctdb_uint32_push(&in->client_packets_recv, buf+offset, &np);
263         offset += np;
264
265         ctdb_uint32_push(&in->node_packets_sent, buf+offset, &np);
266         offset += np;
267
268         ctdb_uint32_push(&in->node_packets_recv, buf+offset, &np);
269         offset += np;
270
271         ctdb_uint32_push(&in->keepalive_packets_sent, buf+offset, &np);
272         offset += np;
273
274         ctdb_uint32_push(&in->keepalive_packets_recv, buf+offset, &np);
275         offset += np;
276
277         ctdb_uint32_push(&in->node.req_call, buf+offset, &np);
278         offset += np;
279
280         ctdb_uint32_push(&in->node.reply_call, buf+offset, &np);
281         offset += np;
282
283         ctdb_uint32_push(&in->node.req_dmaster, buf+offset, &np);
284         offset += np;
285
286         ctdb_uint32_push(&in->node.reply_dmaster, buf+offset, &np);
287         offset += np;
288
289         ctdb_uint32_push(&in->node.reply_error, buf+offset, &np);
290         offset += np;
291
292         ctdb_uint32_push(&in->node.req_message, buf+offset, &np);
293         offset += np;
294
295         ctdb_uint32_push(&in->node.req_control, buf+offset, &np);
296         offset += np;
297
298         ctdb_uint32_push(&in->node.reply_control, buf+offset, &np);
299         offset += np;
300
301         ctdb_uint32_push(&in->client.req_call, buf+offset, &np);
302         offset += np;
303
304         ctdb_uint32_push(&in->client.req_message, buf+offset, &np);
305         offset += np;
306
307         ctdb_uint32_push(&in->client.req_control, buf+offset, &np);
308         offset += np;
309
310         ctdb_uint32_push(&in->timeouts.call, buf+offset, &np);
311         offset += np;
312
313         ctdb_uint32_push(&in->timeouts.control, buf+offset, &np);
314         offset += np;
315
316         ctdb_uint32_push(&in->timeouts.traverse, buf+offset, &np);
317         offset += np;
318
319         ctdb_padding_push(4, buf+offset, &np);
320         offset += np;
321
322         ctdb_latency_counter_push(&in->reclock.ctdbd, buf+offset, &np);
323         offset += np;
324
325         ctdb_latency_counter_push(&in->reclock.recd, buf+offset, &np);
326         offset += np;
327
328         ctdb_uint32_push(&in->locks.num_calls, buf+offset, &np);
329         offset += np;
330
331         ctdb_uint32_push(&in->locks.num_current, buf+offset, &np);
332         offset += np;
333
334         ctdb_uint32_push(&in->locks.num_pending, buf+offset, &np);
335         offset += np;
336
337         ctdb_uint32_push(&in->locks.num_failed, buf+offset, &np);
338         offset += np;
339
340         ctdb_latency_counter_push(&in->locks.latency, buf+offset, &np);
341         offset += np;
342
343         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
344                 ctdb_uint32_push(&in->locks.buckets[i], buf+offset, &np);
345                 offset += np;
346         }
347
348         ctdb_uint32_push(&in->total_calls, buf+offset, &np);
349         offset += np;
350
351         ctdb_uint32_push(&in->pending_calls, buf+offset, &np);
352         offset += np;
353
354         ctdb_uint32_push(&in->childwrite_calls, buf+offset, &np);
355         offset += np;
356
357         ctdb_uint32_push(&in->pending_childwrite_calls, buf+offset, &np);
358         offset += np;
359
360         ctdb_uint32_push(&in->memory_used, buf+offset, &np);
361         offset += np;
362
363         ctdb_uint32_push(&in->__last_counter, buf+offset, &np);
364         offset += np;
365
366         ctdb_uint32_push(&in->max_hop_count, buf+offset, &np);
367         offset += np;
368
369         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
370                 ctdb_uint32_push(&in->hop_count_bucket[i], buf+offset, &np);
371                 offset += np;
372         }
373
374         ctdb_padding_push(4, buf+offset, &np);
375         offset += np;
376
377         ctdb_latency_counter_push(&in->call_latency, buf+offset, &np);
378         offset += np;
379
380         ctdb_latency_counter_push(&in->childwrite_latency, buf+offset, &np);
381         offset += np;
382
383         ctdb_uint32_push(&in->num_recoveries, buf+offset, &np);
384         offset += np;
385
386         ctdb_padding_push(4, buf+offset, &np);
387         offset += np;
388
389         ctdb_timeval_push(&in->statistics_start_time, buf+offset, &np);
390         offset += np;
391
392         ctdb_timeval_push(&in->statistics_current_time, buf+offset, &np);
393         offset += np;
394
395         ctdb_uint32_push(&in->total_ro_delegations, buf+offset, &np);
396         offset += np;
397
398         ctdb_uint32_push(&in->total_ro_revokes, buf+offset, &np);
399         offset += np;
400
401         *npush = offset;
402 }
403
404 static int ctdb_statistics_pull_elems(uint8_t *buf, size_t buflen,
405                                       TALLOC_CTX *mem_ctx,
406                                       struct ctdb_statistics *out,
407                                       size_t *npull)
408 {
409         size_t offset = 0, np;
410         int ret, i;
411
412         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->num_clients,
413                                &np);
414         if (ret != 0) {
415                 return ret;
416         }
417         offset += np;
418
419         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->frozen, &np);
420         if (ret != 0) {
421                 return ret;
422         }
423         offset += np;
424
425         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->recovering,
426                                &np);
427         if (ret != 0) {
428                 return ret;
429         }
430         offset += np;
431
432         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
433                                &out->client_packets_sent, &np);
434         if (ret != 0) {
435                 return ret;
436         }
437         offset += np;
438
439         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
440                                &out->client_packets_recv, &np);
441         if (ret != 0) {
442                 return ret;
443         }
444         offset += np;
445
446         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
447                                &out->node_packets_sent, &np);
448         if (ret != 0) {
449                 return ret;
450         }
451         offset += np;
452
453         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
454                                &out->node_packets_recv, &np);
455         if (ret != 0) {
456                 return ret;
457         }
458         offset += np;
459
460         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
461                                &out->keepalive_packets_sent, &np);
462         if (ret != 0) {
463                 return ret;
464         }
465         offset += np;
466
467         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
468                                &out->keepalive_packets_recv, &np);
469         if (ret != 0) {
470                 return ret;
471         }
472         offset += np;
473
474         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
475                                &out->node.req_call, &np);
476         if (ret != 0) {
477                 return ret;
478         }
479         offset += np;
480
481         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
482                                &out->node.reply_call, &np);
483         if (ret != 0) {
484                 return ret;
485         }
486         offset += np;
487
488         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
489                                &out->node.req_dmaster, &np);
490         if (ret != 0) {
491                 return ret;
492         }
493         offset += np;
494
495         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
496                                &out->node.reply_dmaster, &np);
497         if (ret != 0) {
498                 return ret;
499         }
500         offset += np;
501
502         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
503                                &out->node.reply_error, &np);
504         if (ret != 0) {
505                 return ret;
506         }
507         offset += np;
508
509         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
510                                &out->node.req_message, &np);
511         if (ret != 0) {
512                 return ret;
513         }
514         offset += np;
515
516         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
517                                &out->node.req_control, &np);
518         if (ret != 0) {
519                 return ret;
520         }
521         offset += np;
522
523         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
524                                &out->node.reply_control, &np);
525         if (ret != 0) {
526                 return ret;
527         }
528         offset += np;
529
530         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
531                                &out->client.req_call, &np);
532         if (ret != 0) {
533                 return ret;
534         }
535         offset += np;
536
537         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
538                                &out->client.req_message, &np);
539         if (ret != 0) {
540                 return ret;
541         }
542         offset += np;
543
544         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
545                                &out->client.req_control, &np);
546         if (ret != 0) {
547                 return ret;
548         }
549         offset += np;
550
551         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
552                                &out->timeouts.call, &np);
553         if (ret != 0) {
554                 return ret;
555         }
556         offset += np;
557
558         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
559                                &out->timeouts.control, &np);
560         if (ret != 0) {
561                 return ret;
562         }
563         offset += np;
564
565         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
566                                &out->timeouts.traverse, &np);
567         if (ret != 0) {
568                 return ret;
569         }
570         offset += np;
571
572         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
573         if (ret != 0) {
574                 return ret;
575         }
576         offset += np;
577
578         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
579                                         &out->reclock.ctdbd, &np);
580         if (ret != 0) {
581                 return ret;
582         }
583         offset += np;
584
585         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
586                                         &out->reclock.recd, &np);
587         if (ret != 0) {
588                 return ret;
589         }
590         offset += np;
591
592         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
593                                &out->locks.num_calls, &np);
594         if (ret != 0) {
595                 return ret;
596         }
597         offset += np;
598
599         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
600                                &out->locks.num_current, &np);
601         if (ret != 0) {
602                 return ret;
603         }
604         offset += np;
605
606         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
607                                &out->locks.num_pending, &np);
608         if (ret != 0) {
609                 return ret;
610         }
611         offset += np;
612
613         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
614                                &out->locks.num_failed, &np);
615         if (ret != 0) {
616                 return ret;
617         }
618         offset += np;
619
620         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
621                                         &out->locks.latency, &np);
622         if (ret != 0) {
623                 return ret;
624         }
625         offset += np;
626
627         for (i=0;  i<MAX_COUNT_BUCKETS; i++) {
628                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
629                                        &out->locks.buckets[i], &np);
630                 if (ret != 0) {
631                         return ret;
632                 }
633                 offset += np;
634         }
635
636         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
637                                &out->total_calls, &np);
638         if (ret != 0) {
639                 return ret;
640         }
641         offset += np;
642
643         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
644                                &out->pending_calls, &np);
645         if (ret != 0) {
646                 return ret;
647         }
648         offset += np;
649
650         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
651                                &out->childwrite_calls, &np);
652         if (ret != 0) {
653                 return ret;
654         }
655         offset += np;
656
657         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
658                                &out->pending_childwrite_calls, &np);
659         if (ret != 0) {
660                 return ret;
661         }
662         offset += np;
663
664         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->memory_used,
665                                &np);
666         if (ret != 0) {
667                 return ret;
668         }
669         offset += np;
670
671         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
672                                &out->__last_counter, &np);
673         if (ret != 0) {
674                 return ret;
675         }
676         offset += np;
677
678         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
679                                &out->max_hop_count, &np);
680         if (ret != 0) {
681                 return ret;
682         }
683         offset += np;
684
685         for (i=0;  i<MAX_COUNT_BUCKETS; i++) {
686                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
687                                        &out->hop_count_bucket[i], &np);
688                 if (ret != 0) {
689                         return ret;
690                 }
691                 offset += np;
692         }
693
694         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
695         if (ret != 0) {
696                 return ret;
697         }
698         offset += np;
699
700         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
701                                         &out->call_latency, &np);
702         if (ret != 0) {
703                 return ret;
704         }
705         offset += np;
706
707         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
708                                         &out->childwrite_latency, &np);
709         if (ret != 0) {
710                 return ret;
711         }
712         offset += np;
713
714         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
715                                &out->num_recoveries, &np);
716         if (ret != 0) {
717                 return ret;
718         }
719         offset += np;
720
721         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
722         if (ret != 0) {
723                 return ret;
724         }
725         offset += np;
726
727         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
728                                 &out->statistics_start_time, &np);
729         if (ret != 0) {
730                 return ret;
731         }
732         offset += np;
733
734         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
735                                 &out->statistics_current_time, &np);
736         if (ret != 0) {
737                 return ret;
738         }
739         offset += np;
740
741         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
742                                &out->total_ro_delegations, &np);
743         if (ret != 0) {
744                 return ret;
745         }
746         offset += np;
747
748         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
749                                &out->total_ro_revokes, &np);
750         if (ret != 0) {
751                 return ret;
752         }
753         offset += np;
754
755         *npull = offset;
756         return 0;
757 }
758
759 int ctdb_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
760                          struct ctdb_statistics **out, size_t *npull)
761 {
762         struct ctdb_statistics *val;
763         size_t np;
764         int ret;
765
766         val = talloc(mem_ctx, struct ctdb_statistics);
767         if (val == NULL) {
768                 return ENOMEM;
769         }
770
771         ret = ctdb_statistics_pull_elems(buf, buflen, val, val, &np);
772         if (ret != 0) {
773                 talloc_free(val);
774                 return ret;
775         }
776
777         *out = val;
778         *npull = np;
779         return 0;
780 }
781
782 size_t ctdb_statistics_list_len(struct ctdb_statistics_list *in)
783 {
784         size_t len;
785
786         len = ctdb_int32_len(&in->num) + ctdb_padding_len(4);
787         if (in->num > 0) {
788                 len += in->num * ctdb_statistics_len(&in->stats[0]);
789         }
790
791         return len;
792 }
793
794 void ctdb_statistics_list_push(struct ctdb_statistics_list *in,
795                                uint8_t *buf, size_t *npush)
796 {
797         size_t offset = 0, np;
798         int i;
799
800         ctdb_int32_push(&in->num, buf+offset, &np);
801         offset += np;
802
803         ctdb_padding_push(4, buf+offset, &np);
804         offset += np;
805
806         for (i=0; i<in->num; i++) {
807                 ctdb_statistics_push(&in->stats[i], buf+offset, &np);
808                 offset += np;
809         }
810
811         *npush = offset;
812 }
813
814 int ctdb_statistics_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
815                               struct ctdb_statistics_list **out,
816                               size_t *npull)
817 {
818         struct ctdb_statistics_list *val;
819         size_t offset = 0, np;
820         int ret, i;
821
822         val = talloc(mem_ctx, struct ctdb_statistics_list);
823         if (val == NULL) {
824                 return ENOMEM;
825         }
826
827         ret = ctdb_int32_pull(buf+offset, buflen-offset, &val->num, &np);
828         if (ret != 0) {
829                 goto fail;
830         }
831         offset += np;
832
833         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
834         if (ret != 0) {
835                 goto fail;
836         }
837         offset += np;
838
839         if (val->num == 0) {
840                 val->stats = NULL;
841                 goto done;
842         }
843
844         val->stats = talloc_array(val, struct ctdb_statistics, val->num);
845         if (val->stats == NULL) {
846                 ret = ENOMEM;
847                 goto fail;
848         }
849
850         for (i=0; i<val->num; i++) {
851                 ret = ctdb_statistics_pull_elems(buf+offset, buflen-offset,
852                                                  val, &val->stats[i], &np);
853                 if (ret != 0) {
854                         goto fail;
855                 }
856                 offset += np;
857         }
858
859 done:
860         *out = val;
861         *npull = offset;
862         return 0;
863
864 fail:
865         talloc_free(val);
866         return ret;
867 }
868
869 size_t ctdb_vnn_map_len(struct ctdb_vnn_map *in)
870 {
871         size_t len;
872
873         len = ctdb_uint32_len(&in->generation) + ctdb_uint32_len(&in->size);
874         if (in->size > 0) {
875                 len += in->size * ctdb_uint32_len(&in->map[0]);
876         }
877
878         return len;
879 }
880
881 void ctdb_vnn_map_push(struct ctdb_vnn_map *in, uint8_t *buf, size_t *npush)
882 {
883         size_t offset = 0, np;
884         uint32_t i;
885
886         ctdb_uint32_push(&in->generation, buf+offset, &np);
887         offset += np;
888
889         ctdb_uint32_push(&in->size, buf+offset, &np);
890         offset += np;
891
892         for (i=0; i<in->size; i++) {
893                 ctdb_uint32_push(&in->map[i], buf+offset, &np);
894                 offset += np;
895         }
896
897         *npush = offset;
898 }
899
900 int ctdb_vnn_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
901                       struct ctdb_vnn_map **out, size_t *npull)
902 {
903         struct ctdb_vnn_map *val;
904         size_t offset = 0, np;
905         uint32_t i;
906         int ret;
907
908         val = talloc(mem_ctx, struct ctdb_vnn_map);
909         if (val == NULL) {
910                 return ENOMEM;
911         }
912
913         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->generation,
914                                &np);
915         if (ret != 0) {
916                 goto fail;
917         }
918         offset += np;
919
920         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->size, &np);
921         if (ret != 0) {
922                 goto fail;
923         }
924         offset += np;
925
926         if (val->size == 0) {
927                 val->map = NULL;
928                 goto done;
929         }
930
931         val->map = talloc_array(val, uint32_t, val->size);
932         if (val->map == NULL) {
933                 ret = ENOMEM;
934                 goto fail;
935         }
936
937         for (i=0; i<val->size; i++) {
938                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
939                                        &val->map[i], &np);
940                 if (ret != 0) {
941                         goto fail;
942                 }
943                 offset += np;
944         }
945
946 done:
947         *out = val;
948         *npull = offset;
949         return 0;
950
951 fail:
952         talloc_free(val);
953         return ret;
954 }
955
956 size_t ctdb_dbid_len(struct ctdb_dbid *in)
957 {
958         return ctdb_uint32_len(&in->db_id) +
959                 ctdb_uint8_len(&in->flags) +
960                 ctdb_padding_len(3);
961 }
962
963 void ctdb_dbid_push(struct ctdb_dbid *in, uint8_t *buf, size_t *npush)
964 {
965         size_t offset = 0, np;
966
967         ctdb_uint32_push(&in->db_id, buf+offset, &np);
968         offset += np;
969
970         ctdb_uint8_push(&in->flags, buf+offset, &np);
971         offset += np;
972
973         ctdb_padding_push(3, buf+offset, &np);
974         offset += np;
975
976         *npush = offset;
977 }
978
979 static int ctdb_dbid_pull_elems(uint8_t *buf, size_t buflen,
980                                 TALLOC_CTX *mem_ctx, struct ctdb_dbid *out,
981                                 size_t *npull)
982 {
983         size_t offset = 0, np;
984         int ret;
985
986         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->db_id, &np);
987         if (ret != 0) {
988                 return ret;
989         }
990         offset += np;
991
992         ret = ctdb_uint8_pull(buf+offset, buflen-offset, &out->flags, &np);
993         if (ret != 0) {
994                 return ret;
995         }
996         offset += np;
997
998         ret = ctdb_padding_pull(buf+offset, buflen-offset, 3, &np);
999         if (ret != 0) {
1000                 return ret;
1001         }
1002         offset += np;
1003
1004         *npull = offset;
1005         return 0;
1006 }
1007
1008 int ctdb_dbid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1009                    struct ctdb_dbid **out, size_t *npull)
1010 {
1011         struct ctdb_dbid *val;
1012         size_t np;
1013         int ret;
1014
1015         val = talloc(mem_ctx, struct ctdb_dbid);
1016         if (val == NULL) {
1017                 return ENOMEM;
1018         }
1019
1020         ret = ctdb_dbid_pull_elems(buf, buflen, val, val, &np);
1021         if (ret != 0) {
1022                 talloc_free(val);
1023                 return ret;
1024         }
1025
1026         *out = val;
1027         *npull = np;
1028         return 0;
1029 }
1030
1031 size_t ctdb_dbid_map_len(struct ctdb_dbid_map *in)
1032 {
1033         size_t len;
1034
1035         len = ctdb_uint32_len(&in->num);
1036         if (in->num > 0) {
1037                 len += in->num * ctdb_dbid_len(&in->dbs[0]);
1038         }
1039
1040         return len;
1041 }
1042
1043 void ctdb_dbid_map_push(struct ctdb_dbid_map *in, uint8_t *buf, size_t *npush)
1044 {
1045         size_t offset = 0, np;
1046         uint32_t i;
1047
1048         ctdb_uint32_push(&in->num, buf+offset, &np);
1049         offset += np;
1050
1051         for (i=0; i<in->num; i++) {
1052                 ctdb_dbid_push(&in->dbs[i], buf+offset, &np);
1053                 offset += np;
1054         }
1055
1056         *npush = offset;
1057 }
1058
1059 int ctdb_dbid_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1060                        struct ctdb_dbid_map **out, size_t *npull)
1061 {
1062         struct ctdb_dbid_map *val;
1063         size_t offset = 0, np;
1064         uint32_t i;
1065         int ret;
1066
1067         val = talloc(mem_ctx, struct ctdb_dbid_map);
1068         if (val == NULL) {
1069                 return ENOMEM;
1070         }
1071
1072         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
1073         if (ret != 0) {
1074                 goto fail;
1075         }
1076         offset += np;
1077
1078         if (val->num == 0) {
1079                 val->dbs = NULL;
1080                 goto done;
1081         }
1082
1083         val->dbs = talloc_array(val, struct ctdb_dbid, val->num);
1084         if (val->dbs == NULL) {
1085                 ret = ENOMEM;
1086                 goto fail;
1087         }
1088
1089         for (i=0; i<val->num; i++) {
1090                 ret = ctdb_dbid_pull_elems(buf+offset, buflen-offset, val,
1091                                            &val->dbs[i], &np);
1092                 if (ret != 0) {
1093                         goto fail;
1094                 }
1095                 offset += np;
1096         }
1097
1098 done:
1099         *out = val;
1100         *npull = offset;
1101         return 0;
1102
1103 fail:
1104         talloc_free(val);
1105         return ret;
1106 }
1107
1108 size_t ctdb_pulldb_len(struct ctdb_pulldb *in)
1109 {
1110         return ctdb_uint32_len(&in->db_id) +
1111                 ctdb_uint32_len(&in->lmaster);
1112 }
1113
1114 void ctdb_pulldb_push(struct ctdb_pulldb *in, uint8_t *buf, size_t *npush)
1115 {
1116         size_t offset = 0, np;
1117
1118         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1119         offset += np;
1120
1121         ctdb_uint32_push(&in->lmaster, buf+offset, &np);
1122         offset += np;
1123
1124         *npush = offset;
1125 }
1126
1127 int ctdb_pulldb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1128                      struct ctdb_pulldb **out, size_t *npull)
1129 {
1130         struct ctdb_pulldb *val;
1131         size_t offset = 0, np;
1132         int ret;
1133
1134         val = talloc(mem_ctx, struct ctdb_pulldb);
1135         if (val == NULL) {
1136                 return ENOMEM;
1137         }
1138
1139         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1140         if (ret != 0) {
1141                 talloc_free(val);
1142                 return ret;
1143         }
1144         offset += np;
1145
1146         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->lmaster, &np);
1147         if (ret != 0) {
1148                 talloc_free(val);
1149                 return ret;
1150         }
1151         offset += np;
1152
1153         *out = val;
1154         *npull = offset;
1155         return 0;
1156 }
1157
1158 size_t ctdb_pulldb_ext_len(struct ctdb_pulldb_ext *in)
1159 {
1160         return ctdb_uint32_len(&in->db_id) +
1161                 ctdb_uint32_len(&in->lmaster) +
1162                 ctdb_uint64_len(&in->srvid);
1163 }
1164
1165 void ctdb_pulldb_ext_push(struct ctdb_pulldb_ext *in, uint8_t *buf,
1166                           size_t *npush)
1167 {
1168         size_t offset = 0, np;
1169
1170         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1171         offset += np;
1172
1173         ctdb_uint32_push(&in->lmaster, buf+offset, &np);
1174         offset += np;
1175
1176         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1177         offset += np;
1178
1179         *npush = offset;
1180 }
1181
1182 int ctdb_pulldb_ext_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1183                          struct ctdb_pulldb_ext **out, size_t *npull)
1184 {
1185         struct ctdb_pulldb_ext *val;
1186         size_t offset = 0, np;
1187         int ret;
1188
1189         val = talloc(mem_ctx, struct ctdb_pulldb_ext);
1190         if (val == NULL) {
1191                 return ENOMEM;
1192         }
1193
1194         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1195         if (ret != 0) {
1196                 goto fail;
1197         }
1198         offset += np;
1199
1200         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->lmaster, &np);
1201         if (ret != 0) {
1202                 goto fail;
1203         }
1204         offset += np;
1205
1206         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1207         if (ret != 0) {
1208                 goto fail;
1209         }
1210         offset += np;
1211
1212         *out = val;
1213         *npull = offset;
1214         return 0;
1215
1216 fail:
1217         talloc_free(val);
1218         return ret;
1219 }
1220
1221 size_t ctdb_ltdb_header_len(struct ctdb_ltdb_header *in)
1222 {
1223         return ctdb_uint64_len(&in->rsn) +
1224                 ctdb_uint32_len(&in->dmaster) +
1225                 ctdb_uint32_len(&in->reserved1) +
1226                 ctdb_uint32_len(&in->flags) +
1227                 ctdb_padding_len(4);
1228 }
1229
1230 void ctdb_ltdb_header_push(struct ctdb_ltdb_header *in, uint8_t *buf,
1231                            size_t *npush)
1232 {
1233         size_t offset = 0, np;
1234
1235         ctdb_uint64_push(&in->rsn, buf+offset, &np);
1236         offset += np;
1237
1238         ctdb_uint32_push(&in->dmaster, buf+offset, &np);
1239         offset += np;
1240
1241         ctdb_uint32_push(&in->reserved1, buf+offset, &np);
1242         offset += np;
1243
1244         ctdb_uint32_push(&in->flags, buf+offset, &np);
1245         offset += np;
1246
1247         ctdb_padding_push(4, buf+offset, &np);
1248         offset += np;
1249
1250         *npush = offset;
1251 }
1252
1253 int ctdb_ltdb_header_pull(uint8_t *buf, size_t buflen,
1254                           struct ctdb_ltdb_header *out, size_t *npull)
1255 {
1256         size_t offset = 0, np;
1257         int ret;
1258
1259         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &out->rsn, &np);
1260         if (ret != 0) {
1261                 return ret;
1262         }
1263         offset += np;
1264
1265         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->dmaster, &np);
1266         if (ret != 0) {
1267                 return ret;
1268         }
1269         offset += np;
1270
1271         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->reserved1,
1272                                &np);
1273         if (ret != 0) {
1274                 return ret;
1275         }
1276         offset += np;
1277
1278         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->flags, &np);
1279         if (ret != 0) {
1280                 return ret;
1281         }
1282         offset += np;
1283
1284         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
1285         if (ret != 0) {
1286                 return ret;
1287         }
1288         offset += np;
1289
1290         *npull = offset;
1291         return 0;
1292 }
1293
1294 int ctdb_ltdb_header_extract(TDB_DATA *data, struct ctdb_ltdb_header *header)
1295 {
1296         size_t np;
1297         int ret;
1298
1299         ret = ctdb_ltdb_header_pull(data->dptr, data->dsize, header, &np);
1300         if (ret != 0) {
1301                 return ret;
1302         }
1303
1304         data->dptr += np;
1305         data->dsize -= np;
1306
1307         return 0;
1308 }
1309
1310 size_t ctdb_rec_data_len(struct ctdb_rec_data *in)
1311 {
1312         uint32_t u32;
1313
1314         u32 = ctdb_uint32_len(&in->reqid) +
1315                 ctdb_tdb_datan_len(&in->key) +
1316                 ctdb_tdb_datan_len(&in->data);
1317
1318         if (in->header != NULL) {
1319                 u32 += ctdb_ltdb_header_len(in->header);
1320         }
1321
1322         return ctdb_uint32_len(&u32) + u32;
1323 }
1324
1325 void ctdb_rec_data_push(struct ctdb_rec_data *in, uint8_t *buf, size_t *npush)
1326 {
1327         size_t offset = 0, np;
1328         uint32_t u32;
1329
1330         u32 = ctdb_rec_data_len(in);
1331         ctdb_uint32_push(&u32, buf+offset, &np);
1332         offset += np;
1333
1334         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1335         offset += np;
1336
1337         u32 = ctdb_tdb_data_len(&in->key);
1338         ctdb_uint32_push(&u32, buf+offset, &np);
1339         offset += np;
1340
1341         u32 = ctdb_tdb_data_len(&in->data);
1342         if (in->header != NULL) {
1343                 u32 += ctdb_ltdb_header_len(in->header);
1344         }
1345
1346         ctdb_uint32_push(&u32, buf+offset, &np);
1347         offset += np;
1348
1349         ctdb_tdb_data_push(&in->key, buf+offset, &np);
1350         offset += np;
1351
1352         /* If ltdb header is not NULL, then it is pushed as part of the data */
1353         if (in->header != NULL) {
1354                 ctdb_ltdb_header_push(in->header, buf+offset, &np);
1355                 offset += np;
1356         }
1357         ctdb_tdb_data_push(&in->data, buf+offset, &np);
1358         offset += np;
1359
1360         *npush = offset;
1361 }
1362
1363 static int ctdb_rec_data_pull_data(uint8_t *buf, size_t buflen,
1364                                    uint32_t *reqid,
1365                                    TDB_DATA *key, TDB_DATA *data,
1366                                    size_t *npull)
1367 {
1368         size_t offset = 0, np;
1369         size_t len;
1370         uint32_t u32;
1371         int ret;
1372
1373         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
1374         if (ret != 0) {
1375                 return ret;
1376         }
1377         offset += np;
1378
1379         if (buflen < u32) {
1380                 return EMSGSIZE;
1381         }
1382         len = u32;
1383
1384         ret = ctdb_uint32_pull(buf+offset, len-offset, reqid, &np);
1385         if (ret != 0) {
1386                 return ret;
1387         }
1388         offset += np;
1389
1390         ret = ctdb_uint32_pull(buf+offset, len-offset, &u32, &np);
1391         if (ret != 0) {
1392                 return ret;
1393         }
1394         offset += np;
1395         key->dsize = u32;
1396
1397         ret = ctdb_uint32_pull(buf+offset, len-offset, &u32, &np);
1398         if (ret != 0) {
1399                 return ret;
1400         }
1401         offset += np;
1402         data->dsize = u32;
1403
1404         if (len-offset < key->dsize) {
1405                 return EMSGSIZE;
1406         }
1407
1408         key->dptr = buf+offset;
1409         offset += key->dsize;
1410
1411         if (len-offset < data->dsize) {
1412                 return EMSGSIZE;
1413         }
1414
1415         data->dptr = buf+offset;
1416         offset += data->dsize;
1417
1418         *npull = offset;
1419         return 0;
1420 }
1421
1422 static int ctdb_rec_data_pull_elems(uint8_t *buf, size_t buflen,
1423                                     TALLOC_CTX *mem_ctx,
1424                                     struct ctdb_rec_data *out,
1425                                     size_t *npull)
1426 {
1427         uint32_t reqid;
1428         TDB_DATA key, data;
1429         size_t np;
1430         int ret;
1431
1432         ret = ctdb_rec_data_pull_data(buf, buflen, &reqid, &key, &data, &np);
1433         if (ret != 0) {
1434                 return ret;
1435         }
1436
1437         out->reqid = reqid;
1438
1439         /* Always set header to NULL.  If it is required, extract it using
1440          * ctdb_rec_data_extract_header()
1441          */
1442         out->header = NULL;
1443
1444         out->key.dsize = key.dsize;
1445         if (key.dsize > 0) {
1446                 out->key.dptr = talloc_memdup(mem_ctx, key.dptr, key.dsize);
1447                 if (out->key.dptr == NULL) {
1448                         return ENOMEM;
1449                 }
1450         }
1451
1452         out->data.dsize = data.dsize;
1453         if (data.dsize > 0) {
1454                 out->data.dptr = talloc_memdup(mem_ctx, data.dptr, data.dsize);
1455                 if (out->data.dptr == NULL) {
1456                         return ENOMEM;
1457                 }
1458         }
1459
1460         *npull = np;
1461         return 0;
1462 }
1463
1464 int ctdb_rec_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1465                        struct ctdb_rec_data **out, size_t *npull)
1466 {
1467         struct ctdb_rec_data *val;
1468         size_t np;
1469         int ret;
1470
1471         val = talloc(mem_ctx, struct ctdb_rec_data);
1472         if (val == NULL) {
1473                 return ENOMEM;
1474         }
1475
1476         ret = ctdb_rec_data_pull_elems(buf, buflen, val, val, &np);
1477         if (ret != 0) {
1478                 TALLOC_FREE(val);
1479                 return ret;
1480         }
1481
1482         *out = val;
1483         *npull = np;
1484         return ret;
1485 }
1486
1487 size_t ctdb_rec_buffer_len(struct ctdb_rec_buffer *in)
1488 {
1489         return ctdb_uint32_len(&in->db_id) +
1490                 ctdb_uint32_len(&in->count) +
1491                 in->buflen;
1492 }
1493
1494 void ctdb_rec_buffer_push(struct ctdb_rec_buffer *in, uint8_t *buf,
1495                           size_t *npush)
1496 {
1497         size_t offset = 0, np;
1498
1499         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1500         offset += np;
1501
1502         ctdb_uint32_push(&in->count, buf+offset, &np);
1503         offset += np;
1504
1505         memcpy(buf+offset, in->buf, in->buflen);
1506         offset += in->buflen;
1507
1508         *npush = offset;
1509 }
1510
1511 int ctdb_rec_buffer_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1512                          struct ctdb_rec_buffer **out, size_t *npull)
1513 {
1514         struct ctdb_rec_buffer *val;
1515         size_t offset = 0, np;
1516         size_t length;
1517         int ret;
1518
1519         val = talloc(mem_ctx, struct ctdb_rec_buffer);
1520         if (val == NULL) {
1521                 return ENOMEM;
1522         }
1523
1524         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1525         if (ret != 0) {
1526                 goto fail;
1527         }
1528         offset += np;
1529
1530         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->count, &np);
1531         if (ret != 0) {
1532                 goto fail;
1533         }
1534         offset += np;
1535
1536         /* Since there is no buflen provided, walk the records to
1537          * validate the length of the buffer.
1538          */
1539         val->buf = buf+offset;
1540         val->buflen = buflen-offset;
1541
1542         length = 0;
1543         ret = ctdb_rec_buffer_traverse(val, NULL, &length);
1544         if (ret != 0) {
1545                 goto fail;
1546         }
1547
1548         if (length > buflen-offset) {
1549                 ret = EMSGSIZE;
1550                 goto fail;
1551         }
1552
1553         val->buf = talloc_memdup(val, buf+offset, length);
1554         if (val->buf == NULL) {
1555                 ret = ENOMEM;
1556                 goto fail;
1557         }
1558         val->buflen = length;
1559         offset += length;
1560
1561         *out = val;
1562         *npull = offset;
1563         return 0;
1564
1565 fail:
1566         talloc_free(val);
1567         return ret;
1568 }
1569
1570 struct ctdb_rec_buffer *ctdb_rec_buffer_init(TALLOC_CTX *mem_ctx,
1571                                              uint32_t db_id)
1572 {
1573         struct ctdb_rec_buffer *recbuf;
1574
1575         recbuf = talloc_zero(mem_ctx, struct ctdb_rec_buffer);
1576         if (recbuf == NULL) {
1577                 return recbuf;
1578         }
1579
1580         recbuf->db_id = db_id;
1581
1582         return recbuf;
1583 }
1584
1585 int ctdb_rec_buffer_add(TALLOC_CTX *mem_ctx, struct ctdb_rec_buffer *recbuf,
1586                         uint32_t reqid, struct ctdb_ltdb_header *header,
1587                         TDB_DATA key, TDB_DATA data)
1588 {
1589         struct ctdb_rec_data recdata;
1590         size_t len, np;
1591         uint8_t *ptr;
1592
1593         recdata.reqid = reqid;
1594         recdata.header = header;
1595         recdata.key = key;
1596         recdata.data = data;
1597
1598         len = ctdb_rec_data_len(&recdata);
1599
1600         ptr = talloc_realloc(mem_ctx, recbuf->buf, uint8_t,
1601                              recbuf->buflen + len);
1602         if (ptr == NULL) {
1603                 return ENOMEM;
1604         }
1605
1606         ctdb_rec_data_push(&recdata, &ptr[recbuf->buflen], &np);
1607
1608         recbuf->count++;
1609         recbuf->buf = ptr;
1610         recbuf->buflen += np;
1611         return 0;
1612 }
1613
1614 int ctdb_rec_buffer_traverse(struct ctdb_rec_buffer *recbuf,
1615                              ctdb_rec_parser_func_t func,
1616                              void *private_data)
1617 {
1618         TDB_DATA key, data;
1619         uint32_t reqid;
1620         size_t offset, reclen;
1621         int ret = 0, i;
1622
1623         offset = 0;
1624         for (i=0; i<recbuf->count; i++) {
1625                 ret = ctdb_rec_data_pull_data(&recbuf->buf[offset],
1626                                               recbuf->buflen - offset,
1627                                               &reqid, &key, &data, &reclen);
1628                 if (ret != 0) {
1629                         return ret;
1630                 }
1631
1632                 if (func != NULL) {
1633                         ret = func(reqid, NULL, key, data, private_data);
1634                         if (ret != 0) {
1635                                 break;
1636                         }
1637                 }
1638
1639                 offset += reclen;
1640         }
1641
1642         if (ret != 0) {
1643                 return ret;
1644         }
1645
1646         if (func == NULL) {
1647                 size_t *length = (size_t *)private_data;
1648
1649                 *length = offset;
1650         }
1651
1652         return 0;
1653 }
1654
1655 int ctdb_rec_buffer_write(struct ctdb_rec_buffer *recbuf, int fd)
1656 {
1657         ssize_t n;
1658
1659         n = write(fd, &recbuf->db_id, sizeof(uint32_t));
1660         if (n == -1 || n != sizeof(uint32_t)) {
1661                 return (errno != 0 ? errno : EIO);
1662         }
1663         n = write(fd, &recbuf->count, sizeof(uint32_t));
1664         if (n == -1 || n != sizeof(uint32_t)) {
1665                 return (errno != 0 ? errno : EIO);
1666         }
1667         n = write(fd, &recbuf->buflen, sizeof(size_t));
1668         if (n == -1 || n != sizeof(size_t)) {
1669                 return (errno != 0 ? errno : EIO);
1670         }
1671         n = write(fd, recbuf->buf, recbuf->buflen);
1672         if (n == -1 || n != recbuf->buflen) {
1673                 return (errno != 0 ? errno : EIO);
1674         }
1675
1676         return 0;
1677 }
1678
1679 int ctdb_rec_buffer_read(int fd, TALLOC_CTX *mem_ctx,
1680                          struct ctdb_rec_buffer **out)
1681 {
1682         struct ctdb_rec_buffer *recbuf;
1683         ssize_t n;
1684
1685         recbuf = talloc(mem_ctx, struct ctdb_rec_buffer);
1686         if (recbuf == NULL) {
1687                 return ENOMEM;
1688         }
1689
1690         n = read(fd, &recbuf->db_id, sizeof(uint32_t));
1691         if (n == -1 || n != sizeof(uint32_t)) {
1692                 return (errno != 0 ? errno : EIO);
1693         }
1694         n = read(fd, &recbuf->count, sizeof(uint32_t));
1695         if (n == -1 || n != sizeof(uint32_t)) {
1696                 return (errno != 0 ? errno : EIO);
1697         }
1698         n = read(fd, &recbuf->buflen, sizeof(size_t));
1699         if (n == -1 || n != sizeof(size_t)) {
1700                 return (errno != 0 ? errno : EIO);
1701         }
1702
1703         recbuf->buf = talloc_size(recbuf, recbuf->buflen);
1704         if (recbuf->buf == NULL) {
1705                 return ENOMEM;
1706         }
1707
1708         n = read(fd, recbuf->buf, recbuf->buflen);
1709         if (n == -1 || n != recbuf->buflen) {
1710                 return (errno != 0 ? errno : EIO);
1711         }
1712
1713         *out = recbuf;
1714         return 0;
1715 }
1716
1717 size_t ctdb_traverse_start_len(struct ctdb_traverse_start *in)
1718 {
1719         return ctdb_uint32_len(&in->db_id) +
1720                 ctdb_uint32_len(&in->reqid) +
1721                 ctdb_uint64_len(&in->srvid);
1722 }
1723
1724 void ctdb_traverse_start_push(struct ctdb_traverse_start *in, uint8_t *buf,
1725                               size_t *npush)
1726 {
1727         size_t offset = 0, np;
1728
1729         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1730         offset += np;
1731
1732         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1733         offset += np;
1734
1735         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1736         offset += np;
1737
1738         *npush = offset;
1739 }
1740
1741 int ctdb_traverse_start_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1742                              struct ctdb_traverse_start **out, size_t *npull)
1743 {
1744         struct ctdb_traverse_start *val;
1745         size_t offset = 0, np;
1746         int ret;
1747
1748         val = talloc(mem_ctx, struct ctdb_traverse_start);
1749         if (val == NULL) {
1750                 return ENOMEM;
1751         }
1752
1753         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1754         if (ret != 0) {
1755                 goto fail;
1756         }
1757         offset += np;
1758
1759         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1760         if (ret != 0) {
1761                 goto fail;
1762         }
1763         offset += np;
1764
1765         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1766         if (ret != 0) {
1767                 goto fail;
1768         }
1769         offset += np;
1770
1771         *out = val;
1772         *npull = offset;
1773         return 0;
1774
1775 fail:
1776         talloc_free(val);
1777         return ret;
1778 }
1779
1780 size_t ctdb_traverse_all_len(struct ctdb_traverse_all *in)
1781 {
1782         return ctdb_uint32_len(&in->db_id) +
1783                 ctdb_uint32_len(&in->reqid) +
1784                 ctdb_uint32_len(&in->pnn) +
1785                 ctdb_uint32_len(&in->client_reqid) +
1786                 ctdb_uint64_len(&in->srvid);
1787 }
1788
1789 void ctdb_traverse_all_push(struct ctdb_traverse_all *in, uint8_t *buf,
1790                             size_t *npush)
1791 {
1792         size_t offset = 0, np;
1793
1794         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1795         offset += np;
1796
1797         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1798         offset += np;
1799
1800         ctdb_uint32_push(&in->pnn, buf+offset, &np);
1801         offset += np;
1802
1803         ctdb_uint32_push(&in->client_reqid, buf+offset, &np);
1804         offset += np;
1805
1806         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1807         offset += np;
1808
1809         *npush = offset;
1810 }
1811
1812 int ctdb_traverse_all_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1813                            struct ctdb_traverse_all **out, size_t *npull)
1814 {
1815         struct ctdb_traverse_all *val;
1816         size_t offset = 0, np;
1817         int ret;
1818
1819         val = talloc(mem_ctx, struct ctdb_traverse_all);
1820         if (val == NULL) {
1821                 return ENOMEM;
1822         }
1823
1824         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1825         if (ret != 0) {
1826                 goto fail;
1827         }
1828         offset += np;
1829
1830         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1831         if (ret != 0) {
1832                 goto fail;
1833         }
1834         offset += np;
1835
1836         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
1837         if (ret != 0) {
1838                 goto fail;
1839         }
1840         offset += np;
1841
1842         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->client_reqid,
1843                                &np);
1844         if (ret != 0) {
1845                 goto fail;
1846         }
1847         offset += np;
1848
1849         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1850         if (ret != 0) {
1851                 goto fail;
1852         }
1853         offset += np;
1854
1855         *out = val;
1856         *npull = offset;
1857         return 0;
1858
1859 fail:
1860         talloc_free(val);
1861         return ret;
1862 }
1863
1864 size_t ctdb_traverse_start_ext_len(struct ctdb_traverse_start_ext *in)
1865 {
1866         return ctdb_uint32_len(&in->db_id) +
1867                 ctdb_uint32_len(&in->reqid) +
1868                 ctdb_uint64_len(&in->srvid) +
1869                 ctdb_bool_len(&in->withemptyrecords) +
1870                 ctdb_padding_len(7);
1871 }
1872
1873 void ctdb_traverse_start_ext_push(struct ctdb_traverse_start_ext *in,
1874                                   uint8_t *buf, size_t *npush)
1875 {
1876         size_t offset = 0, np;
1877
1878         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1879         offset += np;
1880
1881         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1882         offset += np;
1883
1884         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1885         offset += np;
1886
1887         ctdb_bool_push(&in->withemptyrecords, buf+offset, &np);
1888         offset += np;
1889
1890         ctdb_padding_push(7, buf+offset, &np);
1891         offset += np;
1892
1893         *npush = offset;
1894 }
1895
1896 int ctdb_traverse_start_ext_pull(uint8_t *buf, size_t buflen,
1897                                  TALLOC_CTX *mem_ctx,
1898                                  struct ctdb_traverse_start_ext **out,
1899                                  size_t *npull)
1900 {
1901         struct ctdb_traverse_start_ext *val;
1902         size_t offset = 0, np;
1903         int ret;
1904
1905         val = talloc(mem_ctx, struct ctdb_traverse_start_ext);
1906         if (val == NULL) {
1907                 return ENOMEM;
1908         }
1909
1910         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1911         if (ret != 0) {
1912                 goto fail;
1913         }
1914         offset += np;
1915
1916         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1917         if (ret != 0) {
1918                 goto fail;
1919         }
1920         offset += np;
1921
1922         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1923         if (ret != 0) {
1924                 goto fail;
1925         }
1926         offset += np;
1927
1928         ret = ctdb_bool_pull(buf+offset, buflen-offset,
1929                              &val->withemptyrecords, &np);
1930         if (ret != 0) {
1931                 goto fail;
1932         }
1933         offset += np;
1934
1935         ret = ctdb_padding_pull(buf+offset, buflen-offset, 7, &np);
1936         if (ret != 0) {
1937                 goto fail;
1938         }
1939         offset += np;
1940
1941         *out = val;
1942         *npull = offset;
1943         return 0;
1944
1945 fail:
1946         talloc_free(val);
1947         return ret;
1948 }
1949
1950 size_t ctdb_traverse_all_ext_len(struct ctdb_traverse_all_ext *in)
1951 {
1952         return ctdb_uint32_len(&in->db_id) +
1953                 ctdb_uint32_len(&in->reqid) +
1954                 ctdb_uint32_len(&in->pnn) +
1955                 ctdb_uint32_len(&in->client_reqid) +
1956                 ctdb_uint64_len(&in->srvid) +
1957                 ctdb_bool_len(&in->withemptyrecords) +
1958                 ctdb_padding_len(7);
1959 }
1960
1961 void ctdb_traverse_all_ext_push(struct ctdb_traverse_all_ext *in,
1962                                 uint8_t *buf, size_t *npush)
1963 {
1964         size_t offset = 0, np;
1965
1966         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1967         offset += np;
1968
1969         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1970         offset += np;
1971
1972         ctdb_uint32_push(&in->pnn, buf+offset, &np);
1973         offset += np;
1974
1975         ctdb_uint32_push(&in->client_reqid, buf+offset, &np);
1976         offset += np;
1977
1978         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1979         offset += np;
1980
1981         ctdb_bool_push(&in->withemptyrecords, buf+offset, &np);
1982         offset += np;
1983
1984         ctdb_padding_push(7, buf+offset, &np);
1985         offset += np;
1986
1987         *npush = offset;
1988 }
1989
1990 int ctdb_traverse_all_ext_pull(uint8_t *buf, size_t buflen,
1991                                TALLOC_CTX *mem_ctx,
1992                                struct ctdb_traverse_all_ext **out,
1993                                size_t *npull)
1994 {
1995         struct ctdb_traverse_all_ext *val;
1996         size_t offset = 0, np;
1997         int ret;
1998
1999         val = talloc(mem_ctx, struct ctdb_traverse_all_ext);
2000         if (val == NULL) {
2001                 return ENOMEM;
2002         }
2003
2004         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
2005         if (ret != 0) {
2006                 goto fail;
2007         }
2008         offset += np;
2009
2010         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
2011         if (ret != 0) {
2012                 goto fail;
2013         }
2014         offset += np;
2015
2016         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
2017         if (ret != 0) {
2018                 goto fail;
2019         }
2020         offset += np;
2021
2022         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->client_reqid,
2023                                &np);
2024         if (ret != 0) {
2025                 goto fail;
2026         }
2027         offset += np;
2028
2029         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
2030         if (ret != 0) {
2031                 goto fail;
2032         }
2033         offset += np;
2034
2035         ret = ctdb_bool_pull(buf+offset, buflen-offset,
2036                              &val->withemptyrecords, &np);
2037         if (ret != 0) {
2038                 goto fail;
2039         }
2040         offset += np;
2041
2042         ret = ctdb_padding_pull(buf+offset, buflen-offset, 7, &np);
2043         if (ret != 0) {
2044                 goto fail;
2045         }
2046         offset += np;
2047
2048         *out = val;
2049         *npull = offset;
2050         return 0;
2051
2052 fail:
2053         talloc_free(val);
2054         return ret;
2055 }
2056
2057 size_t ctdb_sock_addr_len(ctdb_sock_addr *in)
2058 {
2059         return sizeof(ctdb_sock_addr);
2060 }
2061
2062 void ctdb_sock_addr_push(ctdb_sock_addr *in, uint8_t *buf, size_t *npush)
2063 {
2064         memcpy(buf, in, sizeof(ctdb_sock_addr));
2065         *npush = sizeof(ctdb_sock_addr);
2066 }
2067
2068 int ctdb_sock_addr_pull_elems(uint8_t *buf, size_t buflen,
2069                               TALLOC_CTX *mem_ctx, ctdb_sock_addr *out,
2070                               size_t *npull)
2071 {
2072         if (buflen < sizeof(ctdb_sock_addr)) {
2073                 return EMSGSIZE;
2074         }
2075
2076         memcpy(out, buf, sizeof(ctdb_sock_addr));
2077         *npull = sizeof(ctdb_sock_addr);
2078
2079         return 0;
2080 }
2081
2082 int ctdb_sock_addr_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2083                         ctdb_sock_addr **out, size_t *npull)
2084 {
2085         ctdb_sock_addr *val;
2086         size_t np;
2087         int ret;
2088
2089         val = talloc(mem_ctx, ctdb_sock_addr);
2090         if (val == NULL) {
2091                 return ENOMEM;
2092         }
2093
2094         ret = ctdb_sock_addr_pull_elems(buf, buflen, val, val, &np);
2095         if (ret != 0) {
2096                 talloc_free(val);
2097                 return ret;
2098         }
2099
2100         *out = val;
2101         *npull = np;
2102         return ret;
2103 }
2104
2105 size_t ctdb_connection_len(struct ctdb_connection *in)
2106 {
2107         return ctdb_sock_addr_len(&in->src) +
2108                 ctdb_sock_addr_len(&in->dst);
2109 }
2110
2111 void ctdb_connection_push(struct ctdb_connection *in, uint8_t *buf,
2112                           size_t *npush)
2113 {
2114         size_t offset = 0, np;
2115
2116         ctdb_sock_addr_push(&in->src, buf+offset, &np);
2117         offset += np;
2118
2119         ctdb_sock_addr_push(&in->dst, buf+offset, &np);
2120         offset += np;
2121
2122         *npush = offset;
2123 }
2124
2125 static int ctdb_connection_pull_elems(uint8_t *buf, size_t buflen,
2126                                       TALLOC_CTX *mem_ctx,
2127                                       struct ctdb_connection *out,
2128                                       size_t *npull)
2129 {
2130         size_t offset = 0, np;
2131         int ret;
2132
2133         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset,
2134                                         mem_ctx, &out->src, &np);
2135         if (ret != 0) {
2136                 return ret;
2137         }
2138         offset += np;
2139
2140         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset,
2141                                         mem_ctx, &out->dst, &np);
2142         if (ret != 0) {
2143                 return ret;
2144         }
2145         offset += np;
2146
2147         *npull = offset;
2148         return 0;
2149 }
2150
2151 int ctdb_connection_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2152                          struct ctdb_connection **out, size_t *npull)
2153 {
2154         struct ctdb_connection *val;
2155         size_t np;
2156         int ret;
2157
2158         val = talloc(mem_ctx, struct ctdb_connection);
2159         if (val == NULL) {
2160                 return ENOMEM;
2161         }
2162
2163         ret = ctdb_connection_pull_elems(buf, buflen, val, val, &np);
2164         if (ret != 0) {
2165                 talloc_free(val);
2166                 return ret;
2167         }
2168
2169         *out = val;
2170         *npull = np;
2171         return ret;
2172 }
2173
2174 size_t ctdb_connection_list_len(struct ctdb_connection_list *in)
2175 {
2176         size_t len;
2177
2178         len = ctdb_uint32_len(&in->num);
2179         if (in->num > 0) {
2180                 len += in->num * ctdb_connection_len(&in->conn[0]);
2181         }
2182
2183         return len;
2184 }
2185
2186 void ctdb_connection_list_push(struct ctdb_connection_list *in, uint8_t *buf,
2187                                size_t *npush)
2188 {
2189         size_t offset = 0, np;
2190         uint32_t i;
2191
2192         ctdb_uint32_push(&in->num, buf+offset, &np);
2193         offset += np;
2194
2195         for (i=0; i<in->num; i++) {
2196                 ctdb_connection_push(&in->conn[i], buf+offset, &np);
2197                 offset += np;
2198         }
2199
2200         *npush = offset;
2201 }
2202
2203 int ctdb_connection_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2204                               struct ctdb_connection_list **out, size_t *npull)
2205 {
2206         struct ctdb_connection_list *val;
2207         size_t offset = 0, np;
2208         uint32_t i;
2209         int ret;
2210
2211         val = talloc(mem_ctx, struct ctdb_connection_list);
2212         if (val == NULL) {
2213                 return ENOMEM;
2214         }
2215
2216         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
2217         if (ret != 0) {
2218                 goto fail;
2219         }
2220         offset += np;
2221
2222         if (val->num == 0) {
2223                 val->conn = NULL;
2224                 goto done;
2225         }
2226
2227         val->conn = talloc_array(val, struct ctdb_connection, val->num);
2228         if (val->conn == NULL) {
2229                 ret = ENOMEM;
2230                 goto fail;
2231         }
2232
2233         for (i=0; i<val->num; i++) {
2234                 ret = ctdb_connection_pull_elems(buf+offset, buflen-offset,
2235                                                  val, &val->conn[i], &np);
2236                 if (ret != 0) {
2237                         goto fail;
2238                 }
2239                 offset += np;
2240         }
2241
2242 done:
2243         *out = val;
2244         *npull = offset;
2245         return 0;
2246
2247 fail:
2248         talloc_free(val);
2249         return ret;
2250 }
2251
2252 size_t ctdb_tunable_len(struct ctdb_tunable *in)
2253 {
2254         return ctdb_uint32_len(&in->value) +
2255                 ctdb_stringn_len(&in->name);
2256 }
2257
2258 void ctdb_tunable_push(struct ctdb_tunable *in, uint8_t *buf, size_t *npush)
2259 {
2260         size_t offset = 0, np;
2261
2262         ctdb_uint32_push(&in->value, buf+offset, &np);
2263         offset += np;
2264
2265         ctdb_stringn_push(&in->name, buf+offset, &np);
2266         offset += np;
2267
2268         *npush = offset;
2269 }
2270
2271 int ctdb_tunable_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2272                       struct ctdb_tunable **out, size_t *npull)
2273 {
2274         struct ctdb_tunable *val;
2275         size_t offset = 0, np;
2276         int ret;
2277
2278         val = talloc(mem_ctx, struct ctdb_tunable);
2279         if (val == NULL) {
2280                 return ENOMEM;
2281         }
2282
2283         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->value, &np);
2284         if (ret != 0) {
2285                 goto fail;
2286         }
2287         offset += np;
2288
2289         ret = ctdb_stringn_pull(buf+offset, buflen-offset, mem_ctx,
2290                                 &val->name, &np);
2291         if (ret != 0) {
2292                 goto fail;
2293         }
2294         offset += np;
2295
2296         *out = val;
2297         *npull = offset;
2298         return 0;
2299
2300 fail:
2301         talloc_free(val);
2302         return ret;
2303 }
2304
2305 size_t ctdb_node_flag_change_len(struct ctdb_node_flag_change *in)
2306 {
2307         return ctdb_uint32_len(&in->pnn) +
2308                 ctdb_uint32_len(&in->new_flags) +
2309                 ctdb_uint32_len(&in->old_flags);
2310 }
2311
2312 void ctdb_node_flag_change_push(struct ctdb_node_flag_change *in,
2313                                 uint8_t *buf, size_t *npush)
2314 {
2315         size_t offset = 0, np;
2316
2317         ctdb_uint32_push(&in->pnn, buf+offset, &np);
2318         offset += np;
2319
2320         ctdb_uint32_push(&in->new_flags, buf+offset, &np);
2321         offset += np;
2322
2323         ctdb_uint32_push(&in->old_flags, buf+offset, &np);
2324         offset += np;
2325
2326         *npush = offset;
2327 }
2328
2329 int ctdb_node_flag_change_pull(uint8_t *buf, size_t buflen,
2330                                TALLOC_CTX *mem_ctx,
2331                                struct ctdb_node_flag_change **out,
2332                                size_t *npull)
2333 {
2334         struct ctdb_node_flag_change *val;
2335         size_t offset = 0, np;
2336         int ret;
2337
2338         val = talloc(mem_ctx, struct ctdb_node_flag_change);
2339         if (val == NULL) {
2340                 return ENOMEM;
2341         }
2342
2343         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
2344         if (ret != 0) {
2345                 goto fail;
2346         }
2347         offset += np;
2348
2349         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->new_flags,
2350                                &np);
2351         if (ret != 0) {
2352                 goto fail;
2353         }
2354         offset += np;
2355
2356         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->old_flags,
2357                                &np);
2358         if (ret != 0) {
2359                 goto fail;
2360         }
2361         offset += np;
2362
2363         *out = val;
2364         *npull = offset;
2365         return 0;
2366
2367 fail:
2368         talloc_free(val);
2369         return ret;
2370 }
2371
2372 size_t ctdb_var_list_len(struct ctdb_var_list *in)
2373 {
2374         uint32_t u32 = 0;
2375         int i;
2376
2377         for (i=0; i<in->count; i++) {
2378                 u32 += ctdb_string_len(&in->var[i]);
2379         }
2380
2381         return ctdb_uint32_len(&u32) + u32;
2382 }
2383
2384 void ctdb_var_list_push(struct ctdb_var_list *in, uint8_t *buf, size_t *npush)
2385 {
2386         size_t offset = 0, np;
2387         uint32_t u32;
2388         int i;
2389         uint8_t sep = ':';
2390
2391         /* The length only corresponds to the payload size */
2392         u32 = ctdb_var_list_len(in);
2393         u32 -= ctdb_uint32_len(&u32);
2394
2395         ctdb_uint32_push(&u32, buf+offset, &np);
2396         offset += np;
2397
2398         /* The variables are separated by ':' and the complete string is null
2399          * terminated.
2400          */
2401         for (i=0; i<in->count; i++) {
2402                 ctdb_string_push(&in->var[i], buf+offset, &np);
2403                 offset += np;
2404
2405                 if (i < in->count - 1) {
2406                         /* Replace '\0' with ':' */
2407                         ctdb_uint8_push(&sep, buf+offset-1, &np);
2408                 }
2409         }
2410
2411         *npush = offset;
2412 }
2413
2414 int ctdb_var_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2415                        struct ctdb_var_list **out, size_t *npull)
2416 {
2417         struct ctdb_var_list *val;
2418         const char *str, **list;
2419         char *s, *tok, *ptr = NULL;
2420         size_t offset = 0, np;
2421         uint32_t u32;
2422         int ret;
2423
2424         val = talloc_zero(mem_ctx, struct ctdb_var_list);
2425         if (val == NULL) {
2426                 return ENOMEM;
2427         }
2428
2429         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
2430         if (ret != 0) {
2431                 goto fail;
2432         }
2433         offset += np;
2434
2435         if (buflen-offset < u32) {
2436                 ret = EMSGSIZE;
2437                 goto fail;
2438         }
2439
2440         ret = ctdb_string_pull(buf+offset, u32, val, &str, &np);
2441         if (ret != 0) {
2442                 goto fail;
2443         }
2444         offset += np;
2445
2446         s = discard_const(str);
2447         while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
2448                 list = talloc_realloc(val, val->var, const char *,
2449                                       val->count+1);
2450                 if (list == NULL) {
2451                         ret = ENOMEM;
2452                         goto fail;
2453                 }
2454
2455                 val->var = list;
2456
2457                 s = talloc_strdup(val, tok);
2458                 if (s == NULL) {
2459                         ret = ENOMEM;
2460                         goto fail;
2461                 }
2462
2463                 val->var[val->count] = s;
2464                 val->count += 1;
2465                 s = NULL;
2466         }
2467
2468         talloc_free(discard_const(str));
2469         *out = val;
2470         *npull = offset;
2471         return 0;
2472
2473 fail:
2474         talloc_free(val);
2475         return ret;
2476 }
2477
2478 size_t ctdb_tunable_list_len(struct ctdb_tunable_list *in)
2479 {
2480         return ctdb_uint32_len(&in->max_redirect_count) +
2481                 ctdb_uint32_len(&in->seqnum_interval) +
2482                 ctdb_uint32_len(&in->control_timeout) +
2483                 ctdb_uint32_len(&in->traverse_timeout) +
2484                 ctdb_uint32_len(&in->keepalive_interval) +
2485                 ctdb_uint32_len(&in->keepalive_limit) +
2486                 ctdb_uint32_len(&in->recover_timeout) +
2487                 ctdb_uint32_len(&in->recover_interval) +
2488                 ctdb_uint32_len(&in->election_timeout) +
2489                 ctdb_uint32_len(&in->takeover_timeout) +
2490                 ctdb_uint32_len(&in->monitor_interval) +
2491                 ctdb_uint32_len(&in->tickle_update_interval) +
2492                 ctdb_uint32_len(&in->script_timeout) +
2493                 ctdb_uint32_len(&in->monitor_timeout_count) +
2494                 ctdb_uint32_len(&in->script_unhealthy_on_timeout) +
2495                 ctdb_uint32_len(&in->recovery_grace_period) +
2496                 ctdb_uint32_len(&in->recovery_ban_period) +
2497                 ctdb_uint32_len(&in->database_hash_size) +
2498                 ctdb_uint32_len(&in->database_max_dead) +
2499                 ctdb_uint32_len(&in->rerecovery_timeout) +
2500                 ctdb_uint32_len(&in->enable_bans) +
2501                 ctdb_uint32_len(&in->deterministic_public_ips) +
2502                 ctdb_uint32_len(&in->reclock_ping_period) +
2503                 ctdb_uint32_len(&in->no_ip_failback) +
2504                 ctdb_uint32_len(&in->disable_ip_failover) +
2505                 ctdb_uint32_len(&in->verbose_memory_names) +
2506                 ctdb_uint32_len(&in->recd_ping_timeout) +
2507                 ctdb_uint32_len(&in->recd_ping_failcount) +
2508                 ctdb_uint32_len(&in->log_latency_ms) +
2509                 ctdb_uint32_len(&in->reclock_latency_ms) +
2510                 ctdb_uint32_len(&in->recovery_drop_all_ips) +
2511                 ctdb_uint32_len(&in->verify_recovery_lock) +
2512                 ctdb_uint32_len(&in->vacuum_interval) +
2513                 ctdb_uint32_len(&in->vacuum_max_run_time) +
2514                 ctdb_uint32_len(&in->repack_limit) +
2515                 ctdb_uint32_len(&in->vacuum_limit) +
2516                 ctdb_uint32_len(&in->max_queue_depth_drop_msg) +
2517                 ctdb_uint32_len(&in->allow_unhealthy_db_read) +
2518                 ctdb_uint32_len(&in->stat_history_interval) +
2519                 ctdb_uint32_len(&in->deferred_attach_timeout) +
2520                 ctdb_uint32_len(&in->vacuum_fast_path_count) +
2521                 ctdb_uint32_len(&in->lcp2_public_ip_assignment) +
2522                 ctdb_uint32_len(&in->allow_client_db_attach) +
2523                 ctdb_uint32_len(&in->recover_pdb_by_seqnum) +
2524                 ctdb_uint32_len(&in->deferred_rebalance_on_node_add) +
2525                 ctdb_uint32_len(&in->fetch_collapse) +
2526                 ctdb_uint32_len(&in->hopcount_make_sticky) +
2527                 ctdb_uint32_len(&in->sticky_duration) +
2528                 ctdb_uint32_len(&in->sticky_pindown) +
2529                 ctdb_uint32_len(&in->no_ip_takeover) +
2530                 ctdb_uint32_len(&in->db_record_count_warn) +
2531                 ctdb_uint32_len(&in->db_record_size_warn) +
2532                 ctdb_uint32_len(&in->db_size_warn) +
2533                 ctdb_uint32_len(&in->pulldb_preallocation_size) +
2534                 ctdb_uint32_len(&in->no_ip_host_on_all_disabled) +
2535                 ctdb_uint32_len(&in->samba3_hack) +
2536                 ctdb_uint32_len(&in->mutex_enabled) +
2537                 ctdb_uint32_len(&in->lock_processes_per_db) +
2538                 ctdb_uint32_len(&in->rec_buffer_size_limit) +
2539                 ctdb_uint32_len(&in->queue_buffer_size) +
2540                 ctdb_uint32_len(&in->ip_alloc_algorithm) +
2541                 ctdb_uint32_len(&in->allow_mixed_versions);
2542 }
2543
2544 void ctdb_tunable_list_push(struct ctdb_tunable_list *in, uint8_t *buf,
2545                             size_t *npush)
2546 {
2547         size_t offset = 0, np;
2548
2549         ctdb_uint32_push(&in->max_redirect_count, buf+offset, &np);
2550         offset += np;
2551
2552         ctdb_uint32_push(&in->seqnum_interval, buf+offset, &np);
2553         offset += np;
2554
2555         ctdb_uint32_push(&in->control_timeout, buf+offset, &np);
2556         offset += np;
2557
2558         ctdb_uint32_push(&in->traverse_timeout, buf+offset, &np);
2559         offset += np;
2560
2561         ctdb_uint32_push(&in->keepalive_interval, buf+offset, &np);
2562         offset += np;
2563
2564         ctdb_uint32_push(&in->keepalive_limit, buf+offset, &np);
2565         offset += np;
2566
2567         ctdb_uint32_push(&in->recover_timeout, buf+offset, &np);
2568         offset += np;
2569
2570         ctdb_uint32_push(&in->recover_interval, buf+offset, &np);
2571         offset += np;
2572
2573         ctdb_uint32_push(&in->election_timeout, buf+offset, &np);
2574         offset += np;
2575
2576         ctdb_uint32_push(&in->takeover_timeout, buf+offset, &np);
2577         offset += np;
2578
2579         ctdb_uint32_push(&in->monitor_interval, buf+offset, &np);
2580         offset += np;
2581
2582         ctdb_uint32_push(&in->tickle_update_interval, buf+offset, &np);
2583         offset += np;
2584
2585         ctdb_uint32_push(&in->script_timeout, buf+offset, &np);
2586         offset += np;
2587
2588         ctdb_uint32_push(&in->monitor_timeout_count, buf+offset, &np);
2589         offset += np;
2590
2591         ctdb_uint32_push(&in->script_unhealthy_on_timeout, buf+offset, &np);
2592         offset += np;
2593
2594         ctdb_uint32_push(&in->recovery_grace_period, buf+offset, &np);
2595         offset += np;
2596
2597         ctdb_uint32_push(&in->recovery_ban_period, buf+offset, &np);
2598         offset += np;
2599
2600         ctdb_uint32_push(&in->database_hash_size, buf+offset, &np);
2601         offset += np;
2602
2603         ctdb_uint32_push(&in->database_max_dead, buf+offset, &np);
2604         offset += np;
2605
2606         ctdb_uint32_push(&in->rerecovery_timeout, buf+offset, &np);
2607         offset += np;
2608
2609         ctdb_uint32_push(&in->enable_bans, buf+offset, &np);
2610         offset += np;
2611
2612         ctdb_uint32_push(&in->deterministic_public_ips, buf+offset, &np);
2613         offset += np;
2614
2615         ctdb_uint32_push(&in->reclock_ping_period, buf+offset, &np);
2616         offset += np;
2617
2618         ctdb_uint32_push(&in->no_ip_failback, buf+offset, &np);
2619         offset += np;
2620
2621         ctdb_uint32_push(&in->disable_ip_failover, buf+offset, &np);
2622         offset += np;
2623
2624         ctdb_uint32_push(&in->verbose_memory_names, buf+offset, &np);
2625         offset += np;
2626
2627         ctdb_uint32_push(&in->recd_ping_timeout, buf+offset, &np);
2628         offset += np;
2629
2630         ctdb_uint32_push(&in->recd_ping_failcount, buf+offset, &np);
2631         offset += np;
2632
2633         ctdb_uint32_push(&in->log_latency_ms, buf+offset, &np);
2634         offset += np;
2635
2636         ctdb_uint32_push(&in->reclock_latency_ms, buf+offset, &np);
2637         offset += np;
2638
2639         ctdb_uint32_push(&in->recovery_drop_all_ips, buf+offset, &np);
2640         offset += np;
2641
2642         ctdb_uint32_push(&in->verify_recovery_lock, buf+offset, &np);
2643         offset += np;
2644
2645         ctdb_uint32_push(&in->vacuum_interval, buf+offset, &np);
2646         offset += np;
2647
2648         ctdb_uint32_push(&in->vacuum_max_run_time, buf+offset, &np);
2649         offset += np;
2650
2651         ctdb_uint32_push(&in->repack_limit, buf+offset, &np);
2652         offset += np;
2653
2654         ctdb_uint32_push(&in->vacuum_limit, buf+offset, &np);
2655         offset += np;
2656
2657         ctdb_uint32_push(&in->max_queue_depth_drop_msg, buf+offset, &np);
2658         offset += np;
2659
2660         ctdb_uint32_push(&in->allow_unhealthy_db_read, buf+offset, &np);
2661         offset += np;
2662
2663         ctdb_uint32_push(&in->stat_history_interval, buf+offset, &np);
2664         offset += np;
2665
2666         ctdb_uint32_push(&in->deferred_attach_timeout, buf+offset, &np);
2667         offset += np;
2668
2669         ctdb_uint32_push(&in->vacuum_fast_path_count, buf+offset, &np);
2670         offset += np;
2671
2672         ctdb_uint32_push(&in->lcp2_public_ip_assignment, buf+offset, &np);
2673         offset += np;
2674
2675         ctdb_uint32_push(&in->allow_client_db_attach, buf+offset, &np);
2676         offset += np;
2677
2678         ctdb_uint32_push(&in->recover_pdb_by_seqnum, buf+offset, &np);
2679         offset += np;
2680
2681         ctdb_uint32_push(&in->deferred_rebalance_on_node_add, buf+offset, &np);
2682         offset += np;
2683
2684         ctdb_uint32_push(&in->fetch_collapse, buf+offset, &np);
2685         offset += np;
2686
2687         ctdb_uint32_push(&in->hopcount_make_sticky, buf+offset, &np);
2688         offset += np;
2689
2690         ctdb_uint32_push(&in->sticky_duration, buf+offset, &np);
2691         offset += np;
2692
2693         ctdb_uint32_push(&in->sticky_pindown, buf+offset, &np);
2694         offset += np;
2695
2696         ctdb_uint32_push(&in->no_ip_takeover, buf+offset, &np);
2697         offset += np;
2698
2699         ctdb_uint32_push(&in->db_record_count_warn, buf+offset, &np);
2700         offset += np;
2701
2702         ctdb_uint32_push(&in->db_record_size_warn, buf+offset, &np);
2703         offset += np;
2704
2705         ctdb_uint32_push(&in->db_size_warn, buf+offset, &np);
2706         offset += np;
2707
2708         ctdb_uint32_push(&in->pulldb_preallocation_size, buf+offset, &np);
2709         offset += np;
2710
2711         ctdb_uint32_push(&in->no_ip_host_on_all_disabled, buf+offset, &np);
2712         offset += np;
2713
2714         ctdb_uint32_push(&in->samba3_hack, buf+offset, &np);
2715         offset += np;
2716
2717         ctdb_uint32_push(&in->mutex_enabled, buf+offset, &np);
2718         offset += np;
2719
2720         ctdb_uint32_push(&in->lock_processes_per_db, buf+offset, &np);
2721         offset += np;
2722
2723         ctdb_uint32_push(&in->rec_buffer_size_limit, buf+offset, &np);
2724         offset += np;
2725
2726         ctdb_uint32_push(&in->queue_buffer_size, buf+offset, &np);
2727         offset += np;
2728
2729         ctdb_uint32_push(&in->ip_alloc_algorithm, buf+offset, &np);
2730         offset += np;
2731
2732         ctdb_uint32_push(&in->allow_mixed_versions, buf+offset, &np);
2733         offset += np;
2734
2735         *npush = offset;
2736 }
2737
2738 static int ctdb_tunable_list_pull_elems(uint8_t *buf, size_t buflen,
2739                                         TALLOC_CTX *mem_ctx,
2740                                         struct ctdb_tunable_list *out,
2741                                         size_t *npull)
2742 {
2743         size_t offset = 0, np;
2744         int ret;
2745
2746         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2747                                &out->max_redirect_count, &np);
2748         if (ret != 0) {
2749                 return ret;
2750         }
2751         offset += np;
2752
2753         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2754                                &out->seqnum_interval, &np);
2755         if (ret != 0) {
2756                 return ret;
2757         }
2758         offset += np;
2759
2760         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2761                                &out->control_timeout, &np);
2762         if (ret != 0) {
2763                 return ret;
2764         }
2765         offset += np;
2766
2767         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2768                                &out->traverse_timeout, &np);
2769         if (ret != 0) {
2770                 return ret;
2771         }
2772         offset += np;
2773
2774         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2775                                &out->keepalive_interval, &np);
2776         if (ret != 0) {
2777                 return ret;
2778         }
2779         offset += np;
2780
2781         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2782                                &out->keepalive_limit, &np);
2783         if (ret != 0) {
2784                 return ret;
2785         }
2786         offset += np;
2787
2788         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2789                                &out->recover_timeout, &np);
2790         if (ret != 0) {
2791                 return ret;
2792         }
2793         offset += np;
2794
2795         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2796                                &out->recover_interval, &np);
2797         if (ret != 0) {
2798                 return ret;
2799         }
2800         offset += np;
2801
2802         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2803                                &out->election_timeout, &np);
2804         if (ret != 0) {
2805                 return ret;
2806         }
2807         offset += np;
2808
2809         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2810                                &out->takeover_timeout, &np);
2811         if (ret != 0) {
2812                 return ret;
2813         }
2814         offset += np;
2815
2816         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2817                                &out->monitor_interval, &np);
2818         if (ret != 0) {
2819                 return ret;
2820         }
2821         offset += np;
2822
2823         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2824                                &out->tickle_update_interval, &np);
2825         if (ret != 0) {
2826                 return ret;
2827         }
2828         offset += np;
2829
2830         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2831                                &out->script_timeout, &np);
2832         if (ret != 0) {
2833                 return ret;
2834         }
2835         offset += np;
2836
2837         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2838                                &out->monitor_timeout_count, &np);
2839         if (ret != 0) {
2840                 return ret;
2841         }
2842         offset += np;
2843
2844         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2845                                &out->script_unhealthy_on_timeout, &np);
2846         if (ret != 0) {
2847                 return ret;
2848         }
2849         offset += np;
2850
2851         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2852                                &out->recovery_grace_period, &np);
2853         if (ret != 0) {
2854                 return ret;
2855         }
2856         offset += np;
2857
2858         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2859                                &out->recovery_ban_period, &np);
2860         if (ret != 0) {
2861                 return ret;
2862         }
2863         offset += np;
2864
2865         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2866                                &out->database_hash_size, &np);
2867         if (ret != 0) {
2868                 return ret;
2869         }
2870         offset += np;
2871
2872         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2873                                &out->database_max_dead, &np);
2874         if (ret != 0) {
2875                 return ret;
2876         }
2877         offset += np;
2878
2879         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2880                                &out->rerecovery_timeout, &np);
2881         if (ret != 0) {
2882                 return ret;
2883         }
2884         offset += np;
2885
2886         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2887                                &out->enable_bans, &np);
2888         if (ret != 0) {
2889                 return ret;
2890         }
2891         offset += np;
2892
2893         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2894                                &out->deterministic_public_ips, &np);
2895         if (ret != 0) {
2896                 return ret;
2897         }
2898         offset += np;
2899
2900         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2901                                &out->reclock_ping_period, &np);
2902         if (ret != 0) {
2903                 return ret;
2904         }
2905         offset += np;
2906
2907         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2908                                &out->no_ip_failback, &np);
2909         if (ret != 0) {
2910                 return ret;
2911         }
2912         offset += np;
2913
2914         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2915                                &out->disable_ip_failover, &np);
2916         if (ret != 0) {
2917                 return ret;
2918         }
2919         offset += np;
2920
2921         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2922                                &out->verbose_memory_names, &np);
2923         if (ret != 0) {
2924                 return ret;
2925         }
2926         offset += np;
2927
2928         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2929                                &out->recd_ping_timeout, &np);
2930         if (ret != 0) {
2931                 return ret;
2932         }
2933         offset += np;
2934
2935         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2936                                &out->recd_ping_failcount, &np);
2937         if (ret != 0) {
2938                 return ret;
2939         }
2940         offset += np;
2941
2942         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2943                                &out->log_latency_ms, &np);
2944         if (ret != 0) {
2945                 return ret;
2946         }
2947         offset += np;
2948
2949         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2950                                &out->reclock_latency_ms, &np);
2951         if (ret != 0) {
2952                 return ret;
2953         }
2954         offset += np;
2955
2956         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2957                                &out->recovery_drop_all_ips, &np);
2958         if (ret != 0) {
2959                 return ret;
2960         }
2961         offset += np;
2962
2963         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2964                                &out->verify_recovery_lock, &np);
2965         if (ret != 0) {
2966                 return ret;
2967         }
2968         offset += np;
2969
2970         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2971                                &out->vacuum_interval, &np);
2972         if (ret != 0) {
2973                 return ret;
2974         }
2975         offset += np;
2976
2977         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2978                                &out->vacuum_max_run_time, &np);
2979         if (ret != 0) {
2980                 return ret;
2981         }
2982         offset += np;
2983
2984         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2985                                &out->repack_limit, &np);
2986         if (ret != 0) {
2987                 return ret;
2988         }
2989         offset += np;
2990
2991         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2992                                &out->vacuum_limit, &np);
2993         if (ret != 0) {
2994                 return ret;
2995         }
2996         offset += np;
2997
2998         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2999                                &out->max_queue_depth_drop_msg, &np);
3000         if (ret != 0) {
3001                 return ret;
3002         }
3003         offset += np;
3004
3005         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3006                                &out->allow_unhealthy_db_read, &np);
3007         if (ret != 0) {
3008                 return ret;
3009         }
3010         offset += np;
3011
3012         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3013                                &out->stat_history_interval, &np);
3014         if (ret != 0) {
3015                 return ret;
3016         }
3017         offset += np;
3018
3019         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3020                                &out->deferred_attach_timeout, &np);
3021         if (ret != 0) {
3022                 return ret;
3023         }
3024         offset += np;
3025
3026         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3027                                &out->vacuum_fast_path_count, &np);
3028         if (ret != 0) {
3029                 return ret;
3030         }
3031         offset += np;
3032
3033         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3034                                &out->lcp2_public_ip_assignment, &np);
3035         if (ret != 0) {
3036                 return ret;
3037         }
3038         offset += np;
3039
3040         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3041                                &out->allow_client_db_attach, &np);
3042         if (ret != 0) {
3043                 return ret;
3044         }
3045         offset += np;
3046
3047         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3048                                &out->recover_pdb_by_seqnum, &np);
3049         if (ret != 0) {
3050                 return ret;
3051         }
3052         offset += np;
3053
3054         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3055                                &out->deferred_rebalance_on_node_add, &np);
3056         if (ret != 0) {
3057                 return ret;
3058         }
3059         offset += np;
3060
3061         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3062                                &out->fetch_collapse, &np);
3063         if (ret != 0) {
3064                 return ret;
3065         }
3066         offset += np;
3067
3068         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3069                                &out->hopcount_make_sticky, &np);
3070         if (ret != 0) {
3071                 return ret;
3072         }
3073         offset += np;
3074
3075         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3076                                &out->sticky_duration, &np);
3077         if (ret != 0) {
3078                 return ret;
3079         }
3080         offset += np;
3081
3082         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3083                                &out->sticky_pindown, &np);
3084         if (ret != 0) {
3085                 return ret;
3086         }
3087         offset += np;
3088
3089         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3090                                &out->no_ip_takeover, &np);
3091         if (ret != 0) {
3092                 return ret;
3093         }
3094         offset += np;
3095
3096         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3097                                &out->db_record_count_warn, &np);
3098         if (ret != 0) {
3099                 return ret;
3100         }
3101         offset += np;
3102
3103         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3104                                &out->db_record_size_warn, &np);
3105         if (ret != 0) {
3106                 return ret;
3107         }
3108         offset += np;
3109
3110         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3111                                &out->db_size_warn, &np);
3112         if (ret != 0) {
3113                 return ret;
3114         }
3115         offset += np;
3116
3117         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3118                                &out->pulldb_preallocation_size, &np);
3119         if (ret != 0) {
3120                 return ret;
3121         }
3122         offset += np;
3123
3124         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3125                                &out->no_ip_host_on_all_disabled, &np);
3126         if (ret != 0) {
3127                 return ret;
3128         }
3129         offset += np;
3130
3131         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3132                                &out->samba3_hack, &np);
3133         if (ret != 0) {
3134                 return ret;
3135         }
3136         offset += np;
3137
3138         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3139                                &out->mutex_enabled, &np);
3140         if (ret != 0) {
3141                 return ret;
3142         }
3143         offset += np;
3144
3145         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3146                                &out->lock_processes_per_db, &np);
3147         if (ret != 0) {
3148                 return ret;
3149         }
3150         offset += np;
3151
3152         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3153                                &out->rec_buffer_size_limit, &np);
3154         if (ret != 0) {
3155                 return ret;
3156         }
3157         offset += np;
3158
3159         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3160                                &out->queue_buffer_size, &np);
3161         if (ret != 0) {
3162                 return ret;
3163         }
3164         offset += np;
3165
3166         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3167                                &out->ip_alloc_algorithm, &np);
3168         if (ret != 0) {
3169                 return ret;
3170         }
3171         offset += np;
3172
3173         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3174                                &out->allow_mixed_versions, &np);
3175         if (ret != 0) {
3176                 return ret;
3177         }
3178         offset += np;
3179
3180         *npull = offset;
3181         return 0;
3182 }
3183
3184 int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3185                            struct ctdb_tunable_list **out, size_t *npull)
3186 {
3187         struct ctdb_tunable_list *val;
3188         size_t np;
3189         int ret;
3190
3191         val = talloc(mem_ctx, struct ctdb_tunable_list);
3192         if (val == NULL) {
3193                 return ENOMEM;
3194         }
3195
3196         ret = ctdb_tunable_list_pull_elems(buf, buflen, val, val, &np);
3197         if (ret != 0) {
3198                 talloc_free(val);
3199                 return ret;
3200         }
3201
3202         *out = val;
3203         *npull = np;
3204         return 0;
3205 }
3206
3207 size_t ctdb_tickle_list_len(struct ctdb_tickle_list *in)
3208 {
3209         size_t len;
3210
3211         len = ctdb_sock_addr_len(&in->addr) +
3212                 ctdb_uint32_len(&in->num);
3213         if (in->num > 0) {
3214                 len += in->num * ctdb_connection_len(&in->conn[0]);
3215         }
3216
3217         return len;
3218 }
3219
3220 void ctdb_tickle_list_push(struct ctdb_tickle_list *in, uint8_t *buf,
3221                            size_t *npush)
3222 {
3223         size_t offset = 0, np;
3224         uint32_t i;
3225
3226         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3227         offset += np;
3228
3229         ctdb_uint32_push(&in->num, buf+offset, &np);
3230         offset += np;
3231
3232         for (i=0; i<in->num; i++) {
3233                 ctdb_connection_push(&in->conn[i], buf+offset, &np);
3234                 offset += np;
3235         }
3236
3237         *npush = offset;
3238 }
3239
3240 int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3241                            struct ctdb_tickle_list **out, size_t *npull)
3242 {
3243         struct ctdb_tickle_list *val;
3244         size_t offset = 0, np;
3245         uint32_t i;
3246         int ret;
3247
3248         val = talloc(mem_ctx, struct ctdb_tickle_list);
3249         if (val == NULL) {
3250                 return ENOMEM;
3251         }
3252
3253         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, val,
3254                                         &val->addr, &np);
3255         if (ret != 0) {
3256                 goto fail;
3257         }
3258         offset += np;
3259
3260         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
3261         if (ret != 0) {
3262                 goto fail;
3263         }
3264         offset += np;
3265
3266         if (val->num == 0) {
3267                 val->conn = NULL;
3268                 goto done;
3269         }
3270
3271         val->conn = talloc_array(val, struct ctdb_connection, val->num);
3272         if (val->conn == NULL) {
3273                 ret = ENOMEM;
3274                 goto fail;
3275         }
3276
3277         for (i=0; i<val->num; i++) {
3278                 ret = ctdb_connection_pull_elems(buf+offset, buflen-offset,
3279                                                  val, &val->conn[i], &np);
3280                 if (ret != 0) {
3281                         goto fail;
3282                 }
3283                 offset += np;
3284         }
3285
3286 done:
3287         *out = val;
3288         *npull = offset;
3289         return 0;
3290
3291 fail:
3292         talloc_free(val);
3293         return ret;
3294 }
3295
3296 size_t ctdb_addr_info_len(struct ctdb_addr_info *in)
3297 {
3298         return ctdb_sock_addr_len(&in->addr) +
3299                 ctdb_uint32_len(&in->mask) +
3300                 ctdb_stringn_len(&in->iface);
3301 }
3302
3303 void ctdb_addr_info_push(struct ctdb_addr_info *in, uint8_t *buf,
3304                          size_t *npush)
3305 {
3306         size_t offset = 0, np;
3307
3308         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3309         offset += np;
3310
3311         ctdb_uint32_push(&in->mask, buf+offset, &np);
3312         offset += np;
3313
3314         ctdb_stringn_push(&in->iface, buf+offset, &np);
3315         offset += np;
3316
3317         *npush = offset;
3318 }
3319
3320 int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3321                         struct ctdb_addr_info **out, size_t *npull)
3322 {
3323         struct ctdb_addr_info *val;
3324         size_t offset = 0, np;
3325         int ret;
3326
3327         val = talloc(mem_ctx, struct ctdb_addr_info);
3328         if (val == NULL) {
3329                 return ENOMEM;
3330         }
3331
3332         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, val,
3333                                         &val->addr, &np);
3334         if (ret != 0) {
3335                 goto fail;
3336         }
3337         offset += np;
3338
3339         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->mask, &np);
3340         if (ret != 0) {
3341                 goto fail;
3342         }
3343         offset += np;
3344
3345         ret = ctdb_stringn_pull(buf+offset, buflen-offset, val, &val->iface,
3346                                 &np);
3347         if (ret != 0) {
3348                 goto fail;
3349         }
3350         offset += np;
3351
3352         *out = val;
3353         *npull = offset;
3354         return 0;
3355
3356 fail:
3357         talloc_free(val);
3358         return ret;
3359 }
3360
3361 size_t ctdb_transdb_len(struct ctdb_transdb *in)
3362 {
3363         return ctdb_uint32_len(&in->db_id) +
3364                 ctdb_uint32_len(&in->tid);
3365 }
3366
3367 void ctdb_transdb_push(struct ctdb_transdb *in, uint8_t *buf, size_t *npush)
3368 {
3369         size_t offset = 0, np;
3370
3371         ctdb_uint32_push(&in->db_id, buf+offset, &np);
3372         offset += np;
3373
3374         ctdb_uint32_push(&in->tid, buf+offset, &np);
3375         offset += np;
3376
3377         *npush = offset;
3378 }
3379
3380 int ctdb_transdb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3381                      struct ctdb_transdb **out, size_t *npull)
3382 {
3383         struct ctdb_transdb *val;
3384         size_t offset = 0, np;
3385         int ret;
3386
3387         val = talloc(mem_ctx, struct ctdb_transdb);
3388         if (val == NULL) {
3389                 return ENOMEM;
3390         }
3391
3392         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
3393         if (ret != 0) {
3394                 goto fail;
3395         }
3396         offset += np;
3397
3398         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->tid, &np);
3399         if (ret != 0) {
3400                 goto fail;
3401         }
3402         offset += np;
3403
3404         *out = val;
3405         *npull = offset;
3406         return 0;
3407
3408 fail:
3409         talloc_free(val);
3410         return ret;
3411 }
3412
3413 size_t ctdb_uptime_len(struct ctdb_uptime *in)
3414 {
3415         return ctdb_timeval_len(&in->current_time) +
3416                 ctdb_timeval_len(&in->ctdbd_start_time) +
3417                 ctdb_timeval_len(&in->last_recovery_started) +
3418                 ctdb_timeval_len(&in->last_recovery_finished);
3419 }
3420
3421 void ctdb_uptime_push(struct ctdb_uptime *in, uint8_t *buf, size_t *npush)
3422 {
3423         size_t offset = 0, np;
3424
3425         ctdb_timeval_push(&in->current_time, buf+offset, &np);
3426         offset += np;
3427
3428         ctdb_timeval_push(&in->ctdbd_start_time, buf+offset, &np);
3429         offset += np;
3430
3431         ctdb_timeval_push(&in->last_recovery_started, buf+offset, &np);
3432         offset += np;
3433
3434         ctdb_timeval_push(&in->last_recovery_finished, buf+offset, &np);
3435         offset += np;
3436
3437         *npush = offset;
3438 }
3439
3440 int ctdb_uptime_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3441                      struct ctdb_uptime **out, size_t *npull)
3442 {
3443         struct ctdb_uptime *val;
3444         size_t offset = 0, np;
3445         int ret;
3446
3447         val = talloc(mem_ctx, struct ctdb_uptime);
3448         if (val == NULL) {
3449                 return ENOMEM;
3450         }
3451
3452         ret = ctdb_timeval_pull(buf+offset, buflen-offset, &val->current_time,
3453                                 &np);
3454         if (ret != 0) {
3455                 goto fail;
3456         }
3457         offset += np;
3458
3459         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
3460                                 &val->ctdbd_start_time, &np);
3461         if (ret != 0) {
3462                 goto fail;
3463         }
3464         offset += np;
3465
3466         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
3467                                 &val->last_recovery_started, &np);
3468         if (ret != 0) {
3469                 goto fail;
3470         }
3471         offset += np;
3472
3473         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
3474                                 &val->last_recovery_finished, &np);
3475         if (ret != 0) {
3476                 goto fail;
3477         }
3478         offset += np;
3479
3480         *out = val;
3481         *npull = offset;
3482         return 0;
3483
3484 fail:
3485         talloc_free(val);
3486         return ret;
3487 }
3488
3489 size_t ctdb_public_ip_len(struct ctdb_public_ip *in)
3490 {
3491         return ctdb_uint32_len(&in->pnn) +
3492                 ctdb_sock_addr_len(&in->addr);
3493 }
3494
3495 void ctdb_public_ip_push(struct ctdb_public_ip *in, uint8_t *buf,
3496                          size_t *npush)
3497 {
3498         size_t offset = 0, np;
3499
3500         ctdb_uint32_push(&in->pnn, buf+offset, &np);
3501         offset += np;
3502
3503         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3504         offset += np;
3505
3506         *npush = offset;
3507 }
3508
3509 static int ctdb_public_ip_pull_elems(uint8_t *buf, size_t buflen,
3510                                      TALLOC_CTX *mem_ctx,
3511                                      struct ctdb_public_ip *out, size_t *npull)
3512 {
3513         size_t offset = 0, np;
3514         int ret;
3515
3516         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->pnn, &np);
3517         if (ret != 0) {
3518                 return ret;
3519         }
3520         offset += np;
3521
3522         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, mem_ctx,
3523                                         &out->addr, &np);
3524         if (ret != 0) {
3525                 return ret;
3526         }
3527         offset += np;
3528
3529         *npull = offset;
3530         return 0;
3531 }
3532
3533 int ctdb_public_ip_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3534                         struct ctdb_public_ip **out, size_t *npull)
3535 {
3536         struct ctdb_public_ip *val;
3537         size_t np;
3538         int ret;
3539
3540         val = talloc(mem_ctx, struct ctdb_public_ip);
3541         if (val == NULL) {
3542                 return ENOMEM;
3543         }
3544
3545         ret = ctdb_public_ip_pull_elems(buf, buflen, val, val, &np);
3546         if (ret != 0) {
3547                 TALLOC_FREE(val);
3548                 return ret;
3549         }
3550
3551         *out = val;
3552         *npull = np;
3553         return ret;
3554 }
3555
3556 size_t ctdb_public_ip_list_len(struct ctdb_public_ip_list *in)
3557 {
3558         size_t len;
3559
3560         len = ctdb_uint32_len(&in->num);
3561         if (in->num > 0) {
3562                 len += in->num * ctdb_public_ip_len(&in->ip[0]);
3563         }
3564
3565         return len;
3566 }
3567
3568 void ctdb_public_ip_list_push(struct ctdb_public_ip_list *in, uint8_t *buf,
3569                               size_t *npush)
3570 {
3571         size_t offset = 0, np;
3572         uint32_t i;
3573
3574         ctdb_uint32_push(&in->num, buf+offset, &np);
3575         offset += np;
3576
3577         for (i=0; i<in->num; i++) {
3578                 ctdb_public_ip_push(&in->ip[i], buf+offset, &np);
3579                 offset += np;
3580         }
3581
3582         *npush = offset;
3583 }
3584
3585 int ctdb_public_ip_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3586                              struct ctdb_public_ip_list **out, size_t *npull)
3587 {
3588         struct ctdb_public_ip_list *val;
3589         size_t offset = 0, np;
3590         uint32_t i;
3591         int ret;
3592
3593         val = talloc(mem_ctx, struct ctdb_public_ip_list);
3594         if (val == NULL) {
3595                 return ENOMEM;
3596         }
3597
3598         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
3599         if (ret != 0) {
3600                 goto fail;
3601         }
3602         offset += np;
3603
3604         if (val->num == 0) {
3605                 val->ip = NULL;
3606                 goto done;
3607         }
3608
3609         val->ip = talloc_array(val, struct ctdb_public_ip, val->num);
3610         if (val->ip == NULL) {
3611                 ret = ENOMEM;
3612                 goto fail;
3613         }
3614
3615         for (i=0; i<val->num; i++) {
3616                 ret = ctdb_public_ip_pull_elems(buf+offset, buflen-offset,
3617                                                 val->ip, &val->ip[i], &np);
3618                 if (ret != 0) {
3619                         goto fail;
3620                 }
3621                 offset += np;
3622         }
3623
3624 done:
3625         *out = val;
3626         *npull = offset;
3627         return 0;
3628
3629 fail:
3630         talloc_free(val);
3631         return ret;
3632 }
3633
3634 size_t ctdb_node_and_flags_len(struct ctdb_node_and_flags *in)
3635 {
3636         return ctdb_uint32_len(&in->pnn) +
3637                 ctdb_uint32_len(&in->flags) +
3638                 ctdb_sock_addr_len(&in->addr);
3639 }
3640
3641 void ctdb_node_and_flags_push(struct ctdb_node_and_flags *in, uint8_t *buf,
3642                               size_t *npush)
3643 {
3644         size_t offset = 0, np;
3645
3646         ctdb_uint32_push(&in->pnn, buf+offset, &np);
3647         offset += np;
3648
3649         ctdb_uint32_push(&in->flags, buf+offset, &np);
3650         offset += np;
3651
3652         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3653         offset += np;
3654
3655         *npush = offset;
3656 }
3657
3658 static int ctdb_node_and_flags_pull_elems(uint8_t *buf, size_t buflen,
3659                                           TALLOC_CTX *mem_ctx,
3660                                           struct ctdb_node_and_flags *out,
3661                                           size_t *npull)
3662 {
3663         size_t offset = 0, np;
3664         int ret;
3665
3666         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->pnn, &np);
3667         if (ret != 0) {
3668                 return ret;
3669         }
3670         offset += np;
3671
3672         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->flags, &np);
3673         if (ret != 0) {
3674                 return ret;
3675         }
3676         offset += np;
3677
3678         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, mem_ctx,
3679                                         &out->addr, &np);
3680         if (ret != 0) {
3681                 return ret;
3682         }
3683         offset += np;
3684
3685         *npull = offset;
3686         return 0;
3687 }
3688
3689 int ctdb_node_and_flags_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3690                               struct ctdb_node_and_flags **out, size_t *npull)
3691 {
3692         struct ctdb_node_and_flags *val;
3693         size_t np;
3694         int ret;
3695
3696         val = talloc(mem_ctx, struct ctdb_node_and_flags);
3697         if (val == NULL) {
3698                 return ENOMEM;
3699         }
3700
3701         ret = ctdb_node_and_flags_pull_elems(buf, buflen, val, val, &np);
3702         if (ret != 0) {
3703                 TALLOC_FREE(val);
3704                 return ret;
3705         }
3706
3707         *out = val;
3708         *npull = np;
3709         return ret;
3710 }
3711
3712 size_t ctdb_node_map_len(struct ctdb_node_map *in)
3713 {
3714         size_t len;
3715
3716         len = ctdb_uint32_len(&in->num);
3717         if (in->num > 0) {
3718                 len += in->num * ctdb_node_and_flags_len(&in->node[0]);
3719         }
3720
3721         return len;
3722 }
3723
3724 void ctdb_node_map_push(struct ctdb_node_map *in, uint8_t *buf, size_t *npush)
3725 {
3726         size_t offset = 0, np;
3727         uint32_t i;
3728
3729         ctdb_uint32_push(&in->num, buf+offset, &np);
3730         offset += np;
3731
3732         for (i=0; i<in->num; i++) {
3733                 ctdb_node_and_flags_push(&in->node[i], buf+offset, &np);
3734                 offset += np;
3735         }
3736
3737         *npush = offset;
3738 }
3739
3740 int ctdb_node_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3741                        struct ctdb_node_map **out, size_t *npull)
3742 {
3743         struct ctdb_node_map *val;
3744         size_t offset = 0, np;
3745         uint32_t i;
3746         int ret;
3747
3748         val = talloc(mem_ctx, struct ctdb_node_map);
3749         if (val == NULL) {
3750                 return ENOMEM;
3751         }
3752
3753         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
3754         if (ret != 0) {
3755                 goto fail;
3756         }
3757         offset += np;
3758
3759         if (val->num == 0) {
3760                 val->node = NULL;
3761                 goto done;
3762         }
3763
3764         val->node = talloc_array(val, struct ctdb_node_and_flags, val->num);
3765         if (val->node == NULL) {
3766                 ret = ENOMEM;
3767                 goto fail;
3768         }
3769
3770         for (i=0; i<val->num; i++) {
3771                 ret = ctdb_node_and_flags_pull_elems(buf+offset,
3772                                                      buflen-offset,
3773                                                      val->node, &val->node[i],
3774                                                      &np);
3775                 if (ret != 0) {
3776                         goto fail;
3777                 }
3778                 offset += np;
3779         }
3780
3781 done:
3782         *out = val;
3783         *npull = offset;
3784         return 0;
3785
3786 fail:
3787         talloc_free(val);
3788         return ret;
3789 }
3790
3791 size_t ctdb_script_len(struct ctdb_script *in)
3792 {
3793         return ctdb_chararray_len(in->name, MAX_SCRIPT_NAME+1) +
3794                 ctdb_timeval_len(&in->start) +
3795                 ctdb_timeval_len(&in->finished) +
3796                 ctdb_int32_len(&in->status) +
3797                 ctdb_chararray_len(in->output, MAX_SCRIPT_OUTPUT+1) +
3798                 ctdb_padding_len(4);
3799 }
3800
3801 void ctdb_script_push(struct ctdb_script *in, uint8_t *buf, size_t *npush)
3802 {
3803         size_t offset = 0, np;
3804
3805         ctdb_chararray_push(in->name, MAX_SCRIPT_NAME+1, buf+offset, &np);
3806         offset += np;
3807
3808         ctdb_timeval_push(&in->start, buf+offset, &np);
3809         offset += np;
3810
3811         ctdb_timeval_push(&in->finished, buf+offset, &np);
3812         offset += np;
3813
3814         ctdb_int32_push(&in->status, buf+offset, &np);
3815         offset += np;
3816
3817         ctdb_chararray_push(in->output, MAX_SCRIPT_OUTPUT+1, buf+offset, &np);
3818         offset += np;
3819
3820         ctdb_padding_push(4, buf+offset, &np);
3821         offset += np;
3822
3823         *npush = offset;
3824 }
3825
3826 static int ctdb_script_pull_elems(uint8_t *buf, size_t buflen,
3827                                   TALLOC_CTX *mem_ctx,
3828                                   struct ctdb_script *out, size_t *npull)
3829 {
3830         size_t offset = 0, np;
3831         int ret;
3832
3833         ret = ctdb_chararray_pull(buf+offset, buflen-offset,
3834                                   out->name, MAX_SCRIPT_NAME+1, &np);
3835         if (ret != 0) {
3836                 return ret;
3837         }
3838         offset += np;
3839
3840         ret = ctdb_timeval_pull(buf+offset, buflen-offset, &out->start, &np);
3841         if (ret != 0) {
3842                 return ret;
3843         }
3844         offset += np;
3845
3846         ret = ctdb_timeval_pull(buf+offset, buflen-offset, &out->finished,
3847                                 &np);
3848         if (ret != 0) {
3849                 return ret;
3850         }
3851         offset += np;
3852
3853         ret = ctdb_int32_pull(buf+offset, buflen-offset, &out->status, &np);
3854         if (ret != 0) {
3855                 return ret;
3856         }
3857         offset += np;
3858
3859         ret = ctdb_chararray_pull(buf+offset, buflen-offset,
3860                                   out->output, MAX_SCRIPT_OUTPUT+1, &np);
3861         if (ret != 0) {
3862                 return ret;
3863         }
3864         offset += np;
3865
3866         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
3867         if (ret != 0) {
3868                 return ret;
3869         }
3870         offset += np;
3871
3872         *npull = offset;
3873         return 0;
3874 }
3875
3876 int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3877                      struct ctdb_script **out, size_t *npull)
3878 {
3879         struct ctdb_script *val;
3880         size_t np;
3881         int ret;
3882
3883         val = talloc(mem_ctx, struct ctdb_script);
3884         if (val == NULL) {
3885                 return ENOMEM;
3886         }
3887
3888         ret = ctdb_script_pull_elems(buf, buflen, val, val, &np);
3889         if (ret != 0) {
3890                 TALLOC_FREE(val);
3891                 return ret;
3892         }
3893
3894         *out = val;
3895         *npull = np;
3896         return ret;
3897 }
3898
3899 size_t ctdb_script_list_len(struct ctdb_script_list *in)
3900 {
3901         size_t len;
3902
3903         if (in == NULL) {
3904                 return 0;
3905         }
3906
3907         len = ctdb_uint32_len(&in->num_scripts) + ctdb_padding_len(4);
3908         if (in->num_scripts > 0) {
3909                 len += in->num_scripts * ctdb_script_len(&in->script[0]);
3910         }
3911
3912         return len;
3913 }
3914
3915 void ctdb_script_list_push(struct ctdb_script_list *in, uint8_t *buf,
3916                            size_t *npush)
3917 {
3918         size_t offset = 0, np;
3919         uint32_t i;
3920
3921         if (in == NULL) {
3922                 *npush = 0;
3923                 return;
3924         }
3925
3926         ctdb_uint32_push(&in->num_scripts, buf+offset, &np);
3927         offset += np;
3928
3929         ctdb_padding_push(4, buf+offset, &np);
3930         offset += np;
3931
3932         for (i=0; i<in->num_scripts; i++) {
3933                 ctdb_script_push(&in->script[i], buf+offset, &np);
3934                 offset += np;
3935         }
3936
3937         *npush = offset;
3938 }
3939
3940 int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3941                           struct ctdb_script_list **out, size_t *npull)
3942 {
3943         struct ctdb_script_list *val;
3944         size_t offset = 0, np;
3945         uint32_t i;
3946         int ret;
3947
3948         /* If event scripts have never been run, the result will be NULL */
3949         if (buflen == 0) {
3950                 val = NULL;
3951                 goto done;
3952         }
3953
3954         val = talloc(mem_ctx, struct ctdb_script_list);
3955         if (val == NULL) {
3956                 return ENOMEM;
3957         }
3958
3959         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num_scripts,
3960                                &np);
3961         if (ret != 0) {
3962                 goto fail;
3963         }
3964         offset += np;
3965
3966         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
3967         if (ret != 0) {
3968                 goto fail;
3969         }
3970         offset += np;
3971
3972         if (val->num_scripts == 0) {
3973                 val->script = NULL;
3974                 goto done;
3975         }
3976
3977         val->script = talloc_array(val, struct ctdb_script, val->num_scripts);
3978         if (val->script == NULL) {
3979                 ret = ENOMEM;
3980                 goto fail;
3981         }
3982
3983         for (i=0; i<val->num_scripts; i++) {
3984                 ret = ctdb_script_pull_elems(buf+offset, buflen-offset,
3985                                              val, &val->script[i], &np);
3986                 if (ret != 0) {
3987                         goto fail;
3988                 }
3989                 offset += np;
3990         }
3991
3992 done:
3993         *out = val;
3994         *npull = offset;
3995         return 0;
3996
3997 fail:
3998         talloc_free(val);
3999         return ret;
4000 }
4001
4002 size_t ctdb_ban_state_len(struct ctdb_ban_state *in)
4003 {
4004         return ctdb_uint32_len(&in->pnn) +
4005                 ctdb_uint32_len(&in->time);
4006 }
4007
4008 void ctdb_ban_state_push(struct ctdb_ban_state *in, uint8_t *buf,
4009                          size_t *npush)
4010 {
4011         size_t offset = 0, np;
4012
4013         ctdb_uint32_push(&in->pnn, buf+offset, &np);
4014         offset += np;
4015
4016         ctdb_uint32_push(&in->time, buf+offset, &np);
4017         offset += np;
4018
4019         *npush = offset;
4020 }
4021
4022 int ctdb_ban_state_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4023                         struct ctdb_ban_state **out, size_t *npull)
4024 {
4025         struct ctdb_ban_state *val;
4026         size_t offset = 0, np;
4027         int ret;
4028
4029         val = talloc(mem_ctx, struct ctdb_ban_state);
4030         if (val == NULL) {
4031                 return ENOMEM;
4032         }
4033
4034         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
4035         if (ret != 0) {
4036                 goto fail;
4037         }
4038         offset += np;
4039
4040         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->time, &np);
4041         if (ret != 0) {
4042                 goto fail;
4043         }
4044         offset += np;
4045
4046         *out = val;
4047         *npull = offset;
4048         return 0;
4049
4050 fail:
4051         talloc_free(val);
4052         return ret;
4053 }
4054
4055 size_t ctdb_notify_data_len(struct ctdb_notify_data *in)
4056 {
4057         return ctdb_uint64_len(&in->srvid) +
4058                 ctdb_tdb_datan_len(&in->data);
4059 }
4060
4061 void ctdb_notify_data_push(struct ctdb_notify_data *in, uint8_t *buf,
4062                            size_t *npush)
4063 {
4064         size_t offset = 0, np;
4065
4066         ctdb_uint64_push(&in->srvid, buf+offset, &np);
4067         offset += np;
4068
4069         ctdb_tdb_datan_push(&in->data, buf+offset, &np);
4070         offset += np;
4071
4072         *npush = offset;
4073 }
4074
4075 int ctdb_notify_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4076                           struct ctdb_notify_data **out, size_t *npull)
4077 {
4078         struct ctdb_notify_data *val;
4079         size_t offset = 0, np;
4080         int ret;
4081
4082         val = talloc(mem_ctx, struct ctdb_notify_data);
4083         if (val == NULL) {
4084                 return ENOMEM;
4085         }
4086
4087         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
4088         if (ret != 0) {
4089                 goto fail;
4090         }
4091         offset += np;
4092
4093         ret = ctdb_tdb_datan_pull(buf+offset, buflen-offset, val, &val->data,
4094                                   &np);
4095         if (ret != 0) {
4096                 goto fail;
4097         }
4098         offset += np;
4099
4100         *out = val;
4101         *npull = offset;
4102         return 0;
4103
4104 fail:
4105         talloc_free(val);
4106         return ret;
4107 }
4108
4109 size_t ctdb_iface_len(struct ctdb_iface *in)
4110 {
4111         return ctdb_chararray_len(in->name, CTDB_IFACE_SIZE+2) +
4112                 ctdb_uint16_len(&in->link_state) +
4113                 ctdb_uint32_len(&in->references);
4114 }
4115
4116 void ctdb_iface_push(struct ctdb_iface *in, uint8_t *buf, size_t *npush)
4117 {
4118         size_t offset = 0, np;
4119
4120         ctdb_chararray_push(in->name, CTDB_IFACE_SIZE+2, buf+offset, &np);
4121         offset += np;
4122
4123         ctdb_uint16_push(&in->link_state, buf+offset, &np);
4124         offset += np;
4125
4126         ctdb_uint32_push(&in->references, buf+offset, &np);
4127         offset += np;
4128
4129         *npush = offset;
4130 }
4131
4132 static int ctdb_iface_pull_elems(uint8_t *buf, size_t buflen,
4133                                  TALLOC_CTX *mem_ctx,
4134                                  struct ctdb_iface *out, size_t *npull)
4135 {
4136         size_t offset = 0, np;
4137         int ret;
4138
4139         ret = ctdb_chararray_pull(buf+offset, buflen-offset,
4140                                   out->name, CTDB_IFACE_SIZE+2, &np);
4141         if (ret != 0) {
4142                 return ret;
4143         }
4144         offset += np;
4145
4146         ret = ctdb_uint16_pull(buf+offset, buflen-offset, &out->link_state,
4147                                &np);
4148         if (ret != 0) {
4149                 return ret;
4150         }
4151         offset += np;
4152
4153         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->references,
4154                                &np);
4155         if (ret != 0) {
4156                 return ret;
4157         }
4158         offset += np;
4159
4160         *npull = offset;
4161         return 0;
4162 }
4163
4164 int ctdb_iface_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4165                     struct ctdb_iface **out, size_t *npull)
4166 {
4167         struct ctdb_iface *val;
4168         size_t np;
4169         int ret;
4170
4171         val = talloc(mem_ctx, struct ctdb_iface);
4172         if (val == NULL) {
4173                 return ENOMEM;
4174         }
4175
4176         ret = ctdb_iface_pull_elems(buf, buflen, val, val, &np);
4177         if (ret != 0) {
4178                 talloc_free(val);
4179                 return ret;
4180         }
4181
4182         *out = val;
4183         *npull = np;
4184         return ret;
4185 }
4186
4187 size_t ctdb_iface_list_len(struct ctdb_iface_list *in)
4188 {
4189         size_t len;
4190
4191         len = ctdb_uint32_len(&in->num);
4192         if (in->num > 0) {
4193                 len += in->num * ctdb_iface_len(&in->iface[0]);
4194         }
4195
4196         return len;
4197 }
4198
4199 void ctdb_iface_list_push(struct ctdb_iface_list *in, uint8_t *buf,
4200                           size_t *npush)
4201 {
4202         size_t offset = 0, np;
4203         uint32_t i;
4204
4205         ctdb_uint32_push(&in->num, buf+offset, &np);
4206         offset += np;
4207
4208         for (i=0; i<in->num; i++) {
4209                 ctdb_iface_push(&in->iface[i], buf+offset, &np);
4210                 offset += np;
4211         }
4212
4213         *npush = offset;
4214 }
4215
4216 int ctdb_iface_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4217                          struct ctdb_iface_list **out, size_t *npull)
4218 {
4219         struct ctdb_iface_list *val;
4220         size_t offset = 0, np;
4221         uint32_t i;
4222         int ret;
4223
4224         val = talloc(mem_ctx, struct ctdb_iface_list);
4225         if (val == NULL) {
4226                 return ENOMEM;
4227         }
4228
4229         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
4230         if (ret != 0) {
4231                 goto fail;
4232         }
4233         offset += np;
4234
4235         if (val->num == 0) {
4236                 val->iface = NULL;
4237                 goto done;
4238         }
4239
4240         val->iface = talloc_array(val, struct ctdb_iface, val->num);
4241         if (val->iface == NULL) {
4242                 ret = ENOMEM;
4243                 goto fail;
4244         }
4245
4246         for (i=0; i<val->num; i++) {
4247                 ret = ctdb_iface_pull_elems(buf+offset, buflen-offset,
4248                                             val, &val->iface[i], &np);
4249                 if (ret != 0) {
4250                         goto fail;
4251                 }
4252                 offset += np;
4253         }
4254
4255 done:
4256         *out = val;
4257         *npull = offset;
4258         return 0;
4259
4260 fail:
4261         talloc_free(val);
4262         return ret;
4263 }
4264
4265 size_t ctdb_public_ip_info_len(struct ctdb_public_ip_info *in)
4266 {
4267         return ctdb_public_ip_len(&in->ip) +
4268                 ctdb_uint32_len(&in->active_idx) +
4269                 ctdb_iface_list_len(in->ifaces);
4270 }
4271
4272 void ctdb_public_ip_info_push(struct ctdb_public_ip_info *in, uint8_t *buf,
4273                               size_t  *npush)
4274 {
4275         size_t offset = 0, np;
4276
4277         ctdb_public_ip_push(&in->ip, buf+offset, &np);
4278         offset += np;
4279
4280         ctdb_uint32_push(&in->active_idx, buf+offset, &np);
4281         offset += np;
4282
4283         ctdb_iface_list_push(in->ifaces, buf+offset, &np);
4284         offset += np;
4285
4286         *npush = offset;
4287 }
4288
4289 int ctdb_public_ip_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4290                              struct ctdb_public_ip_info **out, size_t *npull)
4291 {
4292         struct ctdb_public_ip_info *val;
4293         size_t offset = 0, np;
4294         int ret;
4295
4296         val = talloc(mem_ctx, struct ctdb_public_ip_info);
4297         if (val == NULL) {
4298                 return ENOMEM;
4299         }
4300
4301         ret = ctdb_public_ip_pull_elems(buf+offset, buflen-offset, val,
4302                                         &val->ip, &np);
4303         if (ret != 0) {
4304                 goto fail;
4305         }
4306         offset += np;
4307
4308         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->active_idx,
4309                                &np);
4310         if (ret != 0) {
4311                 goto fail;
4312         }
4313         offset += np;
4314
4315         ret = ctdb_iface_list_pull(buf+offset, buflen-offset, val,
4316                                    &val->ifaces, &np);
4317         if (ret != 0) {
4318                 goto fail;
4319         }
4320         offset += np;
4321
4322         *out = val;
4323         *npull = offset;
4324         return 0;
4325
4326 fail:
4327         talloc_free(val);
4328         return ret;
4329 }
4330
4331 size_t ctdb_key_data_len(struct ctdb_key_data *in)
4332 {
4333         return ctdb_uint32_len(&in->db_id) +
4334                 ctdb_padding_len(4) +
4335                 ctdb_ltdb_header_len(&in->header) +
4336                 ctdb_tdb_datan_len(&in->key);
4337 }
4338
4339 void ctdb_key_data_push(struct ctdb_key_data *in, uint8_t *buf, size_t *npush)
4340 {
4341         size_t offset = 0, np;
4342
4343         ctdb_uint32_push(&in->db_id, buf+offset, &np);
4344         offset += np;
4345
4346         ctdb_padding_push(4, buf+offset, &np);
4347         offset += np;
4348
4349         ctdb_ltdb_header_push(&in->header, buf+offset, &np);
4350         offset += np;
4351
4352         ctdb_tdb_datan_push(&in->key, buf+offset, &np);
4353         offset += np;
4354
4355         *npush = offset;
4356 }
4357
4358 int ctdb_key_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4359                        struct ctdb_key_data **out, size_t *npull)
4360 {
4361         struct ctdb_key_data *val;
4362         size_t offset = 0, np;
4363         int ret;
4364
4365         val = talloc(mem_ctx, struct ctdb_key_data);
4366         if (val == NULL) {
4367                 return ENOMEM;
4368         }
4369
4370         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
4371         if (ret != 0) {
4372                 goto fail;
4373         }
4374         offset += np;
4375
4376         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4377         if (ret != 0) {
4378                 goto fail;
4379         }
4380         offset += np;
4381
4382         ret = ctdb_ltdb_header_pull(buf+offset, buflen-offset, &val->header,
4383                                     &np);
4384         if (ret != 0) {
4385                 goto fail;
4386         }
4387         offset += np;
4388
4389         ret = ctdb_tdb_datan_pull(buf+offset, buflen-offset, val, &val->key,
4390                                   &np);
4391         if (ret != 0) {
4392                 goto fail;
4393         }
4394         offset += np;
4395
4396         *out = val;
4397         *npull = offset;
4398         return 0;
4399
4400 fail:
4401         talloc_free(val);
4402         return ret;
4403 }
4404
4405 /* In the tdb_data structure marshalling, we are only interested in dsize.
4406  * The dptr value is ignored.  The actual tdb_data blob is stored separately.
4407  *
4408  * This is only required for ctdb_db_statistics and will be dropped in future.
4409  */
4410
4411 static size_t tdb_data_struct_len(TDB_DATA *data)
4412 {
4413         return sizeof(void *) + sizeof(size_t);
4414 }
4415
4416 static void tdb_data_struct_push(TDB_DATA *data, uint8_t *buf, size_t *npush)
4417 {
4418         size_t offset = 0;
4419
4420         memcpy(buf+offset, &data->dptr, sizeof(void *));
4421         offset += sizeof(void *);
4422
4423         memcpy(buf+offset, &data->dsize, sizeof(size_t));
4424         offset += sizeof(size_t);
4425
4426         *npush = offset;
4427 }
4428
4429 static int tdb_data_struct_pull(uint8_t *buf, size_t buflen, TDB_DATA *data,
4430                                 size_t *npull)
4431 {
4432         size_t offset = 0;
4433         void *ptr;
4434
4435         if (buflen-offset < sizeof(void *)) {
4436                 return EMSGSIZE;
4437         }
4438
4439         memcpy(&ptr, buf+offset, sizeof(void *));
4440         offset += sizeof(void *);
4441         data->dptr = NULL;
4442
4443         if (buflen-offset < sizeof(size_t)) {
4444                 return EMSGSIZE;
4445         }
4446
4447         memcpy(&data->dsize, buf+offset, sizeof(size_t));
4448         offset += sizeof(size_t);
4449
4450         *npull = offset;
4451         return 0;
4452 }
4453
4454 size_t ctdb_db_statistics_len(struct ctdb_db_statistics *in)
4455 {
4456         TDB_DATA data = { 0 };
4457         size_t len;
4458         uint32_t u32 = 0;
4459         int i;
4460
4461         len = ctdb_uint32_len(&in->locks.num_calls) +
4462                 ctdb_uint32_len(&in->locks.num_current) +
4463                 ctdb_uint32_len(&in->locks.num_pending) +
4464                 ctdb_uint32_len(&in->locks.num_failed) +
4465                 ctdb_latency_counter_len(&in->locks.latency) +
4466                 MAX_COUNT_BUCKETS *
4467                         ctdb_uint32_len(&in->locks.buckets[0]) +
4468                 ctdb_latency_counter_len(&in->vacuum.latency) +
4469                 ctdb_uint32_len(&in->db_ro_delegations) +
4470                 ctdb_uint32_len(&in->db_ro_revokes) +
4471                 MAX_COUNT_BUCKETS *
4472                         ctdb_uint32_len(&in->hop_count_bucket[0]) +
4473                 ctdb_uint32_len(&in->num_hot_keys) +
4474                 ctdb_padding_len(4) +
4475                 MAX_HOT_KEYS *
4476                         (ctdb_uint32_len(&u32) + ctdb_padding_len(4) +
4477                          tdb_data_struct_len(&data));
4478
4479         for (i=0; i<MAX_HOT_KEYS; i++) {
4480                 len += ctdb_tdb_data_len(&in->hot_keys[i].key);
4481         }
4482
4483         return len;
4484 }
4485
4486 void ctdb_db_statistics_push(struct ctdb_db_statistics *in, uint8_t *buf,
4487                              size_t *npush)
4488 {
4489         size_t offset = 0, np;
4490         uint32_t num_hot_keys;
4491         int i;
4492
4493         ctdb_uint32_push(&in->locks.num_calls, buf+offset, &np);
4494         offset += np;
4495
4496         ctdb_uint32_push(&in->locks.num_current, buf+offset, &np);
4497         offset += np;
4498
4499         ctdb_uint32_push(&in->locks.num_pending, buf+offset, &np);
4500         offset += np;
4501
4502         ctdb_uint32_push(&in->locks.num_failed, buf+offset, &np);
4503         offset += np;
4504
4505         ctdb_latency_counter_push(&in->locks.latency, buf+offset, &np);
4506         offset += np;
4507
4508         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
4509                 ctdb_uint32_push(&in->locks.buckets[i], buf+offset, &np);
4510                 offset += np;
4511         }
4512
4513         ctdb_latency_counter_push(&in->vacuum.latency, buf+offset, &np);
4514         offset += np;
4515
4516         ctdb_uint32_push(&in->db_ro_delegations, buf+offset, &np);
4517         offset += np;
4518
4519         ctdb_uint32_push(&in->db_ro_revokes, buf+offset, &np);
4520         offset += np;
4521
4522         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
4523                 ctdb_uint32_push(&in->hop_count_bucket[i], buf+offset, &np);
4524                 offset += np;
4525         }
4526
4527         num_hot_keys = MAX_HOT_KEYS;
4528         ctdb_uint32_push(&num_hot_keys, buf+offset, &np);
4529         offset += np;
4530
4531         ctdb_padding_push(4, buf+offset, &np);
4532         offset += np;
4533
4534         for (i=0; i<MAX_HOT_KEYS; i++) {
4535                 ctdb_uint32_push(&in->hot_keys[i].count, buf+offset, &np);
4536                 offset += np;
4537
4538                 ctdb_padding_push(4, buf+offset, &np);
4539                 offset += np;
4540
4541                 tdb_data_struct_push(&in->hot_keys[i].key, buf+offset, &np);
4542                 offset += np;
4543         }
4544
4545         for (i=0; i<MAX_HOT_KEYS; i++) {
4546                 ctdb_tdb_data_push(&in->hot_keys[i].key, buf+offset, &np);
4547                 offset += np;
4548         }
4549
4550         *npush = offset;
4551 }
4552
4553 static int ctdb_db_statistics_pull_elems(uint8_t *buf, size_t buflen,
4554                                          TALLOC_CTX *mem_ctx,
4555                                          struct ctdb_db_statistics *out,
4556                                          size_t *npull)
4557 {
4558         size_t offset = 0, np;
4559         int ret, i;
4560
4561         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4562                                &out->locks.num_calls, &np);
4563         if (ret != 0) {
4564                 return ret;
4565         }
4566         offset += np;
4567
4568         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4569                                &out->locks.num_current, &np);
4570         if (ret != 0) {
4571                 return ret;
4572         }
4573         offset += np;
4574
4575         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4576                                &out->locks.num_pending, &np);
4577         if (ret != 0) {
4578                 return ret;
4579         }
4580         offset += np;
4581
4582         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4583                                &out->locks.num_failed, &np);
4584         if (ret != 0) {
4585                 return ret;
4586         }
4587         offset += np;
4588
4589         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
4590                                         &out->locks.latency, &np);
4591         if (ret != 0) {
4592                 return ret;
4593         }
4594         offset += np;
4595
4596         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
4597                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4598                                        &out->locks.buckets[i], &np);
4599                 if (ret != 0) {
4600                         return ret;
4601                 }
4602                 offset += np;
4603         }
4604
4605         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
4606                                         &out->vacuum.latency, &np);
4607         if (ret != 0) {
4608                 return ret;
4609         }
4610         offset += np;
4611
4612         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4613                                &out->db_ro_delegations, &np);
4614         if (ret != 0) {
4615                 return ret;
4616         }
4617         offset += np;
4618
4619         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4620                                &out->db_ro_revokes, &np);
4621         if (ret != 0) {
4622                 return ret;
4623         }
4624         offset += np;
4625
4626         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
4627                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4628                                        &out->hop_count_bucket[i], &np);
4629                 if (ret != 0) {
4630                         return ret;
4631                 }
4632                 offset += np;
4633         }
4634
4635         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4636                                &out->num_hot_keys, &np);
4637         if (ret != 0) {
4638                 return ret;
4639         }
4640         offset += np;
4641
4642         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4643         if (ret != 0) {
4644                 return ret;
4645         }
4646         offset += np;
4647
4648         for (i=0; i<MAX_HOT_KEYS; i++) {
4649                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
4650                                        &out->hot_keys[i].count, &np);
4651                 if (ret != 0) {
4652                         return ret;
4653                 }
4654                 offset += np;
4655
4656                 ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4657                 if (ret != 0) {
4658                         return ret;
4659                 }
4660                 offset += np;
4661
4662                 ret = tdb_data_struct_pull(buf+offset, buflen-offset,
4663                                            &out->hot_keys[i].key, &np);
4664                 if (ret != 0) {
4665                         return ret;
4666                 }
4667                 offset += np;
4668         }
4669
4670         for (i=0; i<MAX_HOT_KEYS; i++) {
4671                 ret = ctdb_tdb_data_pull(buf+offset,
4672                                          out->hot_keys[i].key.dsize,
4673                                          out, &out->hot_keys[i].key, &np);
4674                 if (ret != 0) {
4675                         return ret;
4676                 }
4677                 offset += np;
4678         }
4679
4680         *npull = offset;
4681         return 0;
4682 }
4683
4684 int ctdb_db_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4685                             struct ctdb_db_statistics **out, size_t *npull)
4686 {
4687         struct ctdb_db_statistics *val;
4688         size_t np;
4689         int ret;
4690
4691         val = talloc(mem_ctx, struct ctdb_db_statistics);
4692         if (val == NULL) {
4693                 return ENOMEM;
4694         }
4695
4696         ret = ctdb_db_statistics_pull_elems(buf, buflen, val, val, &np);
4697         if (ret != 0) {
4698                 talloc_free(val);
4699                 return ret;
4700         }
4701
4702         *out = val;
4703         *npull = np;
4704         return 0;
4705 }
4706
4707 size_t ctdb_pid_srvid_len(struct ctdb_pid_srvid *in)
4708 {
4709         return ctdb_pid_len(&in->pid) +
4710                 ctdb_uint64_len(&in->srvid);
4711 }
4712
4713 void ctdb_pid_srvid_push(struct ctdb_pid_srvid *in, uint8_t *buf,
4714                          size_t *npush)
4715 {
4716         size_t offset = 0, np;
4717
4718         ctdb_pid_push(&in->pid, buf+offset, &np);
4719         offset += np;
4720
4721         ctdb_uint64_push(&in->srvid, buf+offset, &np);
4722         offset += np;
4723
4724         *npush = offset;
4725 }
4726
4727 int ctdb_pid_srvid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4728                         struct ctdb_pid_srvid **out, size_t *npull)
4729 {
4730         struct ctdb_pid_srvid *val;
4731         size_t offset = 0, np;
4732         int ret;
4733
4734         val = talloc(mem_ctx, struct ctdb_pid_srvid);
4735         if (val == NULL) {
4736                 return ENOMEM;
4737         }
4738
4739         ret = ctdb_pid_pull(buf+offset, buflen-offset, &val->pid, &np);
4740         if (ret != 0) {
4741                 goto fail;
4742         }
4743         offset += np;
4744
4745         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
4746         if (ret != 0) {
4747                 goto fail;
4748         }
4749         offset += np;
4750
4751         *out = val;
4752         *npull = offset;
4753         return 0;
4754
4755 fail:
4756         talloc_free(val);
4757         return ret;
4758 }
4759
4760 size_t ctdb_election_message_len(struct ctdb_election_message *in)
4761 {
4762         return ctdb_uint32_len(&in->num_connected) +
4763                 ctdb_padding_len(4) +
4764                 ctdb_timeval_len(&in->priority_time) +
4765                 ctdb_uint32_len(&in->pnn) +
4766                 ctdb_uint32_len(&in->node_flags);
4767 }
4768
4769 void ctdb_election_message_push(struct ctdb_election_message *in,
4770                                 uint8_t *buf, size_t *npush)
4771 {
4772         size_t offset = 0, np;
4773
4774         ctdb_uint32_push(&in->num_connected, buf+offset, &np);
4775         offset += np;
4776
4777         ctdb_padding_push(4, buf+offset, &np);
4778         offset += np;
4779
4780         ctdb_timeval_push(&in->priority_time, buf+offset, &np);
4781         offset += np;
4782
4783         ctdb_uint32_push(&in->pnn, buf+offset, &np);
4784         offset += np;
4785
4786         ctdb_uint32_push(&in->node_flags, buf+offset, &np);
4787         offset += np;
4788
4789         *npush = offset;
4790 }
4791
4792 int ctdb_election_message_pull(uint8_t *buf, size_t buflen,
4793                                TALLOC_CTX *mem_ctx,
4794                                struct ctdb_election_message **out,
4795                                size_t *npull)
4796 {
4797         struct ctdb_election_message *val;
4798         size_t offset = 0, np;
4799         int ret;
4800
4801         val = talloc(mem_ctx, struct ctdb_election_message);
4802         if (val == NULL) {
4803                 return ENOMEM;
4804         }
4805
4806         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num_connected,
4807                                &np);
4808         if (ret != 0) {
4809                 goto fail;
4810         }
4811         offset += np;
4812
4813         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4814         if (ret != 0) {
4815                 goto fail;
4816         }
4817         offset += np;
4818
4819         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
4820                                 &val->priority_time, &np);
4821         if (ret != 0) {
4822                 goto fail;
4823         }
4824         offset += np;
4825
4826         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
4827         if (ret != 0) {
4828                 goto fail;
4829         }
4830         offset += np;
4831
4832         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->node_flags,
4833                                &np);
4834         if (ret != 0) {
4835                 goto fail;
4836         }
4837         offset += np;
4838
4839         *out = val;
4840         *npull = offset;
4841         return 0;
4842
4843 fail:
4844         talloc_free(val);
4845         return ret;
4846 }
4847
4848 size_t ctdb_srvid_message_len(struct ctdb_srvid_message *in)
4849 {
4850         return ctdb_uint32_len(&in->pnn) +
4851                 ctdb_padding_len(4) +
4852                 ctdb_uint64_len(&in->srvid);
4853 }
4854
4855 void ctdb_srvid_message_push(struct ctdb_srvid_message *in, uint8_t *buf,
4856                              size_t *npush)
4857 {
4858         size_t offset = 0, np;
4859
4860         ctdb_uint32_push(&in->pnn, buf+offset, &np);
4861         offset += np;
4862
4863         ctdb_padding_push(4, buf+offset, &np);
4864         offset += np;
4865
4866         ctdb_uint64_push(&in->srvid, buf+offset, &np);
4867         offset += np;
4868
4869         *npush = offset;
4870 }
4871
4872 int ctdb_srvid_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4873                             struct ctdb_srvid_message **out, size_t *npull)
4874 {
4875         struct ctdb_srvid_message *val;
4876         size_t offset = 0, np;
4877         int ret;
4878
4879         val = talloc(mem_ctx, struct ctdb_srvid_message);
4880         if (val == NULL) {
4881                 return ENOMEM;
4882         }
4883
4884         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
4885         if (ret != 0) {
4886                 goto fail;
4887         }
4888         offset += np;
4889
4890         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4891         if (ret != 0) {
4892                 goto fail;
4893         }
4894         offset += np;
4895
4896         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
4897         if (ret != 0) {
4898                 goto fail;
4899         }
4900         offset += np;
4901
4902         *out = val;
4903         *npull = offset;
4904         return 0;
4905
4906 fail:
4907         talloc_free(val);
4908         return ret;
4909 }
4910
4911 size_t ctdb_disable_message_len(struct ctdb_disable_message *in)
4912 {
4913         return ctdb_uint32_len(&in->pnn) +
4914                 ctdb_padding_len(4) +
4915                 ctdb_uint64_len(&in->srvid) +
4916                 ctdb_uint32_len(&in->timeout) +
4917                 ctdb_padding_len(4);
4918 }
4919
4920 void ctdb_disable_message_push(struct ctdb_disable_message *in, uint8_t *buf,
4921                                size_t *npush)
4922 {
4923         size_t offset = 0, np;
4924
4925         ctdb_uint32_push(&in->pnn, buf+offset, &np);
4926         offset += np;
4927
4928         ctdb_padding_push(4, buf+offset, &np);
4929         offset += np;
4930
4931         ctdb_uint64_push(&in->srvid, buf+offset, &np);
4932         offset += np;
4933
4934         ctdb_uint32_push(&in->timeout, buf+offset, &np);
4935         offset += np;
4936
4937         ctdb_padding_push(4, buf+offset, &np);
4938         offset += np;
4939
4940         *npush = offset;
4941 }
4942
4943 int ctdb_disable_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4944                               struct ctdb_disable_message **out,
4945                               size_t *npull)
4946 {
4947         struct ctdb_disable_message *val;
4948         size_t offset = 0, np;
4949         int ret;
4950
4951         val = talloc(mem_ctx, struct ctdb_disable_message);
4952         if (val == NULL) {
4953                 return ENOMEM;
4954         }
4955
4956         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
4957         if (ret != 0) {
4958                 goto fail;
4959         }
4960         offset += np;
4961
4962         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4963         if (ret != 0) {
4964                 goto fail;
4965         }
4966         offset += np;
4967
4968         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
4969         if (ret != 0) {
4970                 goto fail;
4971         }
4972         offset += np;
4973
4974         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->timeout, &np);
4975         if (ret != 0) {
4976                 goto fail;
4977         }
4978         offset += np;
4979
4980         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
4981         if (ret != 0) {
4982                 goto fail;
4983         }
4984         offset += np;
4985
4986         *out = val;
4987         *npull = offset;
4988         return 0;
4989
4990 fail:
4991         talloc_free(val);
4992         return ret;
4993 }
4994
4995 size_t ctdb_server_id_len(struct ctdb_server_id *in)
4996 {
4997         return ctdb_uint64_len(&in->pid) +
4998                 ctdb_uint32_len(&in->task_id) +
4999                 ctdb_uint32_len(&in->vnn) +
5000                 ctdb_uint64_len(&in->unique_id);
5001 }
5002
5003 void ctdb_server_id_push(struct ctdb_server_id *in, uint8_t *buf,
5004                          size_t *npush)
5005 {
5006         size_t offset = 0, np;
5007
5008         ctdb_uint64_push(&in->pid, buf+offset, &np);
5009         offset += np;
5010
5011         ctdb_uint32_push(&in->task_id, buf+offset, &np);
5012         offset += np;
5013
5014         ctdb_uint32_push(&in->vnn, buf+offset, &np);
5015         offset += np;
5016
5017         ctdb_uint64_push(&in->unique_id, buf+offset, &np);
5018         offset += np;
5019
5020         *npush = offset;
5021 }
5022
5023 int ctdb_server_id_pull(uint8_t *buf, size_t buflen,
5024                         struct ctdb_server_id *out, size_t *npull)
5025 {
5026         size_t offset = 0, np;
5027         int ret;
5028
5029         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &out->pid, &np);
5030         if (ret != 0) {
5031                 return ret;
5032         }
5033         offset += np;
5034
5035         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->task_id, &np);
5036         if (ret != 0) {
5037                 return ret;
5038         }
5039         offset += np;
5040
5041         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->vnn, &np);
5042         if (ret != 0) {
5043                 return ret;
5044         }
5045         offset += np;
5046
5047         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &out->unique_id,
5048                                &np);
5049         if (ret != 0) {
5050                 return ret;
5051         }
5052         offset += np;
5053
5054         *npull = offset;
5055         return 0;
5056 }
5057
5058 size_t ctdb_g_lock_len(struct ctdb_g_lock *in)
5059 {
5060         return ctdb_uint32_len(&in->type) +
5061                 ctdb_padding_len(4) +
5062                 ctdb_server_id_len(&in->sid);
5063 }
5064
5065 void ctdb_g_lock_push(struct ctdb_g_lock *in, uint8_t *buf, size_t *npush)
5066 {
5067         size_t offset = 0, np;
5068         uint32_t type;
5069
5070         type = in->type;
5071         ctdb_uint32_push(&type, buf+offset, &np);
5072         offset += np;
5073
5074         ctdb_padding_push(4, buf+offset, &np);
5075         offset += np;
5076
5077         ctdb_server_id_push(&in->sid, buf+offset, &np);
5078         offset += np;
5079
5080         *npush = offset;
5081 }
5082
5083 int ctdb_g_lock_pull(uint8_t *buf, size_t buflen, struct ctdb_g_lock *out,
5084                      size_t *npull)
5085 {
5086         size_t offset = 0, np;
5087         int ret;
5088         uint32_t type;
5089
5090         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &type, &np);
5091         if (ret != 0) {
5092                 return ret;
5093         }
5094         offset += np;
5095
5096         if (type == 0) {
5097                 out->type = CTDB_G_LOCK_READ;
5098         } else if (type == 1) {
5099                 out->type = CTDB_G_LOCK_WRITE;
5100         } else {
5101                 return EPROTO;
5102         }
5103
5104         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
5105         if (ret != 0) {
5106                 return ret;
5107         }
5108         offset += np;
5109
5110         ret = ctdb_server_id_pull(buf+offset, buflen-offset, &out->sid, &np);
5111         if (ret != 0) {
5112                 return ret;
5113         }
5114         offset += np;
5115
5116         *npull = offset;
5117         return 0;
5118 }
5119
5120 size_t ctdb_g_lock_list_len(struct ctdb_g_lock_list *in)
5121 {
5122         size_t len = 0;
5123
5124         if (in->num > 0) {
5125                 len += in->num * ctdb_g_lock_len(&in->lock[0]);
5126         }
5127
5128         return len;
5129 }
5130
5131 void ctdb_g_lock_list_push(struct ctdb_g_lock_list *in, uint8_t *buf,
5132                            size_t *npush)
5133 {
5134         size_t offset = 0, np;
5135         uint32_t i;
5136
5137         for (i=0; i<in->num; i++) {
5138                 ctdb_g_lock_push(&in->lock[i], buf+offset, &np);
5139                 offset += np;
5140         }
5141
5142         *npush = offset;
5143 }
5144
5145 int ctdb_g_lock_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
5146                           struct ctdb_g_lock_list **out, size_t *npull)
5147 {
5148         struct ctdb_g_lock_list *val;
5149         struct ctdb_g_lock lock = { 0 };
5150         size_t offset = 0, np;
5151         uint32_t i;
5152         int ret;
5153
5154         val = talloc(mem_ctx, struct ctdb_g_lock_list);
5155         if (val == NULL) {
5156                 return ENOMEM;
5157         }
5158
5159         if (buflen == 0) {
5160                 val->lock = NULL;
5161                 val->num = 0;
5162                 goto done;
5163         }
5164
5165         val->num = buflen / ctdb_g_lock_len(&lock);
5166
5167         val->lock = talloc_array(val, struct ctdb_g_lock, val->num);
5168         if (val->lock == NULL) {
5169                 ret = ENOMEM;
5170                 goto fail;
5171         }
5172
5173         for (i=0; i<val->num; i++) {
5174                 ret = ctdb_g_lock_pull(buf+offset, buflen-offset,
5175                                        &val->lock[i], &np);
5176                 if (ret != 0) {
5177                         goto fail;
5178                 }
5179                 offset += np;
5180         }
5181
5182 done:
5183         *out = val;
5184         *npull = offset;
5185         return 0;
5186
5187 fail:
5188         talloc_free(val);
5189         return ENOMEM;
5190 }