2 Copyright (C) 2010 - 2020 Proxmox Server Solutions GmbH
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Author: Dietmar Maurer <dietmar@proxmox.com>
21 #define G_LOG_DOMAIN "dcdb"
25 #endif /* HAVE_CONFIG_H */
33 #include <sys/types.h>
35 #include <arpa/inet.h>
36 #include <sys/epoll.h>
40 #include "cfs-utils.h"
46 memdb_index_t
*master
;
55 const guchar csum
[32],
58 g_return_if_fail(dfsm
!= NULL
);
59 g_return_if_fail(path
!= NULL
);
60 g_return_if_fail(csum
!= NULL
);
64 iov
[0].iov_base
= (char *)csum
;
67 iov
[1].iov_base
= (char *)path
;
68 iov
[1].iov_len
= strlen(path
) + 1;
70 if (!cfs_is_quorate())
73 dcdb_message_t msg_type
= request
?
74 DCDB_MESSAGE_CFS_UNLOCK_REQUEST
: DCDB_MESSAGE_CFS_UNLOCK
;
76 dfsm_send_message_sync(dfsm
, msg_type
, iov
, 2, NULL
);
80 dcdb_parse_unlock_request(
87 g_return_val_if_fail(msg
!= NULL
, FALSE
);
88 g_return_val_if_fail(path
!= NULL
, FALSE
);
89 g_return_val_if_fail(csum
!= NULL
, FALSE
);
92 cfs_critical("received short unlock message (%zu < 33)", msg_len
);
96 char *msg_str
= (char *) msg
;
98 *csum
= (guchar
*) msg_str
;
99 msg_str
+= 32; msg_len
-= 32;
102 if ((*path
)[msg_len
- 1] != 0) {
103 cfs_critical("received mailformed unlock message - 'path' not terminated");
112 dcdb_send_fuse_message(
114 dcdb_message_t msg_type
,
124 iov
[0].iov_base
= (char *)&size
;
125 iov
[0].iov_len
= sizeof(size
);
127 iov
[1].iov_base
= (char *)&offset
;
128 iov
[1].iov_len
= sizeof(offset
);
130 guint32 pathlen
= path
? strlen(path
) + 1 : 0;
131 iov
[2].iov_base
= (char *)&pathlen
;
132 iov
[2].iov_len
= sizeof(pathlen
);
134 guint32 tolen
= to
? strlen(to
) + 1 : 0;
135 iov
[3].iov_base
= (char *)&tolen
;
136 iov
[3].iov_len
= sizeof(tolen
);
138 iov
[4].iov_base
= (char *)&flags
;
139 iov
[4].iov_len
= sizeof(flags
);
141 iov
[5].iov_base
= (char *)path
;
142 iov
[5].iov_len
= pathlen
;
144 iov
[6].iov_base
= (char *)to
;
145 iov
[6].iov_len
= tolen
;
147 iov
[7].iov_base
= (char *)buf
;
148 iov
[7].iov_len
= size
;
151 memset(&rc
, 0, sizeof(rc
));
154 if (!cfs_is_quorate())
157 if (dfsm_send_message_sync(dfsm
, msg_type
, iov
, 8, &rc
))
164 dcdb_parse_fuse_message(
175 g_return_val_if_fail(msg
!= NULL
, FALSE
);
176 g_return_val_if_fail(path
!= NULL
, FALSE
);
177 g_return_val_if_fail(to
!= NULL
, FALSE
);
178 g_return_val_if_fail(buf
!= NULL
, FALSE
);
179 g_return_val_if_fail(size
!= NULL
, FALSE
);
180 g_return_val_if_fail(offset
!= NULL
, FALSE
);
181 g_return_val_if_fail(flags
!= NULL
, FALSE
);
184 cfs_critical("received short fuse message (%zu < 20)", msg_len
);
188 const uint8_t *msg_ptr
= msg
;
190 *size
= *((guint32
*)msg_ptr
);
191 msg_ptr
+= 4; msg_len
-= 4;
193 *offset
= *((guint32
*)msg_ptr
);
194 msg_ptr
+= 4; msg_len
-= 4;
196 guint32 pathlen
= *((guint32
*)msg_ptr
);
197 msg_ptr
+= 4; msg_len
-= 4;
199 guint32 tolen
= *((guint32
*)msg_ptr
);
200 msg_ptr
+= 4; msg_len
-= 4;
202 *flags
= *((guint32
*)msg_ptr
);
203 msg_ptr
+= 4; msg_len
-= 4;
205 if (msg_len
!= ((*size
) + pathlen
+ tolen
)) {
206 cfs_critical("received mailformed fuse message");
210 *path
= (char *)msg_ptr
;
211 msg_ptr
+= pathlen
; msg_len
-= pathlen
;
214 if ((*path
)[pathlen
- 1] != 0) {
215 cfs_critical("received mailformed fuse message - 'path' not terminated");
223 *to
= (char *)msg_ptr
;
224 msg_ptr
+= tolen
; msg_len
-= tolen
;
227 if ((*to
)[tolen
- 1] != 0) {
228 cfs_critical("received mailformed fuse message - 'to' not terminated");
236 *buf
= (*size
) ? (const char*)msg_ptr
: NULL
;
242 dcdb_send_update_inode(
244 memdb_tree_entry_t
*te
)
246 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
247 g_return_val_if_fail(te
!= NULL
, FALSE
);
250 struct iovec iov
[20];
252 uint32_t namelen
= strlen(te
->name
) + 1;
254 iov
[0].iov_base
= (char *)&te
->parent
;
255 iov
[0].iov_len
= sizeof(te
->parent
);
256 iov
[1].iov_base
= (char *)&te
->inode
;
257 iov
[1].iov_len
= sizeof(te
->inode
);
258 iov
[2].iov_base
= (char *)&te
->version
;
259 iov
[2].iov_len
= sizeof(te
->version
);
260 iov
[3].iov_base
= (char *)&te
->writer
;
261 iov
[3].iov_len
= sizeof(te
->writer
);
262 iov
[4].iov_base
= (char *)&te
->mtime
;
263 iov
[4].iov_len
= sizeof(te
->mtime
);
264 iov
[5].iov_base
= (char *)&te
->size
;
265 iov
[5].iov_len
= sizeof(te
->size
);
266 iov
[6].iov_base
= (char *)&namelen
;
267 iov
[6].iov_len
= sizeof(namelen
);
268 iov
[7].iov_base
= (char *)&te
->type
;
269 iov
[7].iov_len
= sizeof(te
->type
);
270 iov
[8].iov_base
= (char *)te
->name
;
271 iov
[8].iov_len
= namelen
;
274 if (te
->type
== DT_REG
&& te
->size
) {
275 iov
[9].iov_base
= (char *)te
->data
.value
;
276 iov
[9].iov_len
= te
->size
;
280 if (dfsm_send_update(dfsm
, iov
, len
) != CS_OK
)
287 dcdb_parse_update_inode(
292 cfs_critical("received short message (msg_len < 40)");
296 char *msg_ptr
= (char *) msg
;
298 guint64 parent
= *((guint64
*)msg_ptr
);
299 msg_ptr
+= 8; msg_len
-= 8;
300 guint64 inode
= *((guint64
*)msg_ptr
);
301 msg_ptr
+= 8; msg_len
-= 8;
302 guint64 version
= *((guint64
*)msg_ptr
);
303 msg_ptr
+= 8; msg_len
-= 8;
305 guint32 writer
= *((guint32
*)msg_ptr
);
306 msg_ptr
+= 4; msg_len
-= 4;
307 guint32 mtime
= *((guint32
*)msg_ptr
);
308 msg_ptr
+= 4; msg_len
-= 4;
309 guint32 size
= *((guint32
*)msg_ptr
);
310 msg_ptr
+= 4; msg_len
-= 4;
311 guint32 namelen
= *((guint32
*)msg_ptr
);
312 msg_ptr
+= 4; msg_len
-= 4;
314 char type
= *((char *)msg_ptr
);
315 msg_ptr
+= 1; msg_len
-= 1;
317 if (!(type
== DT_REG
|| type
== DT_DIR
)) {
318 cfs_critical("received mailformed message (unknown inode type %d)", type
);
322 if (msg_len
!= (size
+ namelen
)) {
323 cfs_critical("received mailformed message (msg_len != (size + namelen))");
327 char *name
= msg_ptr
;
328 msg_ptr
+= namelen
; msg_len
-= namelen
;
330 const void *data
= msg_ptr
;
332 if (name
[namelen
- 1] != 0) {
333 cfs_critical("received mailformed message (name[namelen-1] != 0)");
337 memdb_tree_entry_t
*te
= memdb_tree_entry_new(name
);
342 te
->version
= version
;
349 if (te
->type
== DT_REG
&& te
->size
) {
350 te
->data
.value
= g_memdup(data
, te
->size
);
351 if (!te
->data
.value
) {
352 memdb_tree_entry_free(te
);
361 dcdb_sync_corosync_conf(
363 gboolean notify_corosync
)
365 g_return_if_fail(memdb
!= NULL
);
368 gpointer data
= NULL
;
370 len
= memdb_read(memdb
, "corosync.conf", &data
);
374 guint64 new_version
= cluster_config_version(data
, len
);
376 cfs_critical("unable to parse cluster config_version");
380 char *old_data
= NULL
;
381 gsize old_length
= 0;
382 guint64 old_version
= 0;
385 if (!g_file_get_contents(HOST_CLUSTER_CONF_FN
, &old_data
, &old_length
, &err
)) {
386 if (!g_error_matches(err
, G_FILE_ERROR
, G_FILE_ERROR_NOENT
)) {
387 cfs_critical("unable to read cluster config file '%s' - %s",
388 HOST_CLUSTER_CONF_FN
, err
->message
);
393 old_version
= cluster_config_version(old_data
, old_length
);
396 /* test if something changed - return if no changes */
397 if (data
&& old_data
&& (old_length
== len
) &&
398 !memcmp(data
, old_data
, len
))
401 if (new_version
< old_version
) {
402 cfs_critical("local corosync.conf is newer");
406 if (!atomic_write_file(HOST_CLUSTER_CONF_FN
, data
, len
, 0644, 0))
409 cfs_message("wrote new corosync config '%s' (version = %" G_GUINT64_FORMAT
")",
410 HOST_CLUSTER_CONF_FN
, new_version
);
412 if (notify_corosync
&& old_version
) {
413 /* tell corosync that there is a new config file */
414 cfs_debug ("run corosync-cfgtool -R");
415 int status
= system("corosync-cfgtool -R >/dev/null 2>&1");
416 if (WIFEXITED(status
) && WEXITSTATUS(status
) != 0) {
417 cfs_critical("corosync-cfgtool -R failed with exit code %d\n", WEXITSTATUS(status
));
419 cfs_debug ("end corosync-cfgtool -R");
435 unsigned int *res_len
)
437 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
438 g_return_val_if_fail(data
!= NULL
, FALSE
);
440 memdb_t
*memdb
= (memdb_t
*)data
;
442 g_return_val_if_fail(memdb
->root
!= NULL
, FALSE
);
444 cfs_debug("enter %s %016" PRIX64
" %08X", __func__
, (uint64_t) memdb
->root
->version
, memdb
->root
->mtime
);
446 g_mutex_lock (&memdb
->mutex
);
447 memdb_index_t
*idx
= memdb_encode_index(memdb
->index
, memdb
->root
);
448 g_mutex_unlock (&memdb
->mutex
);
451 *res_len
= idx
->bytes
;
460 memdb_index_t
*idx
[])
462 g_return_val_if_fail(idx
!= NULL
, -1);
464 cfs_debug("enter %s", __func__
);
468 /* try select most actual data - compare 'version' an 'time of last write'
469 * NOTE: syncinfo members are sorted
471 for (int i
= 0; i
< node_count
; i
++) {
475 memdb_index_t
*leaderidx
= idx
[leader
];
477 if (idx
[i
]->version
== leaderidx
->version
&&
478 idx
[i
]->mtime
> leaderidx
->mtime
) {
480 } else if (idx
[i
]->version
> leaderidx
->version
) {
486 cfs_debug ("leave %s (%d)", __func__
, leader
);
492 dcdb_create_and_send_updates(
495 memdb_index_t
*master
,
497 memdb_index_t
*idx
[])
499 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
500 g_return_val_if_fail(memdb
!= NULL
, FALSE
);
501 g_return_val_if_fail(master
!= NULL
, FALSE
);
503 cfs_debug("enter %s", __func__
);
505 gboolean res
= FALSE
;
507 GHashTable
*updates
= g_hash_table_new(g_int64_hash
, g_int64_equal
);
511 g_mutex_lock (&memdb
->mutex
);
513 for (int n
= 0; n
< node_count
; n
++) {
514 memdb_index_t
*slave
= idx
[n
];
521 for (int i
= 0; i
< master
->size
; i
++) {
522 guint64 inode
= master
->entries
[i
].inode
;
523 while (j
< slave
->size
&& slave
->entries
[j
].inode
< inode
)
526 if (memcmp(&slave
->entries
[j
], &master
->entries
[i
],
527 sizeof(memdb_index_extry_t
)) == 0) {
531 if (g_hash_table_lookup(updates
, &inode
))
534 cfs_debug("found different inode %d %016" PRIX64
, i
, (uint64_t) inode
);
536 memdb_tree_entry_t
*te
, *cpy
;
538 if (!(te
= g_hash_table_lookup(memdb
->index
, &inode
))) {
539 cfs_critical("can get inode data for inode %016" PRIX64
, (uint64_t) inode
);
543 cpy
= memdb_tree_entry_copy(te
, 1);
544 g_hash_table_replace(updates
, &cpy
->inode
, cpy
);
548 g_mutex_unlock (&memdb
->mutex
);
556 cfs_message("start sending inode updates");
558 g_hash_table_iter_init (&iter
, updates
);
559 while (g_hash_table_iter_next (&iter
, &key
, &value
)) {
560 memdb_tree_entry_t
*te
= (memdb_tree_entry_t
*)value
;
563 if (!dcdb_send_update_inode(dfsm
, te
)) {
564 /* tolerate error here */
565 cfs_critical("sending update inode failed %016" PRIX64
, (uint64_t) te
->inode
);
567 cfs_debug("sent update inode %016" PRIX64
, (uint64_t) te
->inode
);
570 memdb_tree_entry_free(te
);
573 cfs_message("sent all (%d) updates", count
);
575 if (dfsm_send_update_complete(dfsm
) != CS_OK
) {
576 cfs_critical("failed to send UPDATE_COMPLETE message");
584 g_hash_table_destroy(updates
);
586 cfs_debug("leave %s (%d)", __func__
, res
);
592 dcdb_process_state_update(
595 dfsm_sync_info_t
*syncinfo
)
597 g_return_val_if_fail(dfsm
!= NULL
, -1);
598 g_return_val_if_fail(data
!= NULL
, -1);
599 g_return_val_if_fail(syncinfo
!= NULL
, -1);
601 memdb_t
*memdb
= (memdb_t
*)data
;
603 cfs_debug("enter %s", __func__
);
605 dcdb_sync_info_t
*localsi
= g_new0(dcdb_sync_info_t
, 1);
609 syncinfo
->data
= localsi
;
611 memdb_index_t
*idx
[syncinfo
->node_count
];
613 for (int i
= 0; i
< syncinfo
->node_count
; i
++) {
614 dfsm_node_info_t
*ni
= &syncinfo
->nodes
[i
];
616 if (ni
->state_len
< sizeof(memdb_index_t
)) {
617 cfs_critical("received short memdb index (len < sizeof(memdb_index_t))");
621 idx
[i
] = (memdb_index_t
*)ni
->state
;
623 if (ni
->state_len
!= idx
[i
]->bytes
) {
624 cfs_critical("received mailformed memdb index (len != idx->bytes)");
629 /* select leader - set mode */
630 int leader
= dcdb_select_leader(syncinfo
->node_count
, idx
);
632 cfs_critical("unable to select leader failed");
636 cfs_message("leader is %d/%d", syncinfo
->nodes
[leader
].nodeid
, syncinfo
->nodes
[leader
].pid
);
638 memdb_index_t
*leaderidx
= idx
[leader
];
639 localsi
->master
= leaderidx
;
641 GString
*synced_member_ids
= g_string_new(NULL
);
642 g_string_append_printf(synced_member_ids
, "%d/%d", syncinfo
->nodes
[leader
].nodeid
, syncinfo
->nodes
[leader
].pid
);
644 for (int i
= 0; i
< syncinfo
->node_count
; i
++) {
645 dfsm_node_info_t
*ni
= &syncinfo
->nodes
[i
];
649 if (leaderidx
->bytes
== idx
[i
]->bytes
&&
650 memcmp(leaderidx
, idx
[i
], leaderidx
->bytes
) == 0) {
652 g_string_append_printf(synced_member_ids
, ", %d/%d", ni
->nodeid
, ni
->pid
);
655 if (dfsm_nodeid_is_local(dfsm
, ni
->nodeid
, ni
->pid
))
656 localsi
->idx
= idx
[i
];
658 cfs_message("synced members: %s", synced_member_ids
->str
);
659 g_string_free(synced_member_ids
, 1);
662 if (dfsm_nodeid_is_local(dfsm
, syncinfo
->nodes
[leader
].nodeid
, syncinfo
->nodes
[leader
].pid
)) {
663 if (!dcdb_create_and_send_updates(dfsm
, memdb
, leaderidx
, syncinfo
->node_count
, idx
))
674 dfsm_sync_info_t
*syncinfo
,
680 g_return_val_if_fail(dfsm
!= NULL
, -1);
681 g_return_val_if_fail(data
!= NULL
, -1);
682 g_return_val_if_fail(msg
!= NULL
, -1);
683 g_return_val_if_fail(syncinfo
!= NULL
, -1);
684 g_return_val_if_fail(syncinfo
->data
!= NULL
, -1);
686 cfs_debug("enter %s", __func__
);
688 memdb_tree_entry_t
*te
;
690 if (!(te
= dcdb_parse_update_inode(msg
, msg_len
)))
693 cfs_debug("received inode update %016" PRIX64
" from node %d",
694 (uint64_t) te
->inode
, nodeid
);
696 dcdb_sync_info_t
*localsi
= (dcdb_sync_info_t
*)syncinfo
->data
;
698 localsi
->updates
= g_list_append(localsi
->updates
, te
);
707 dfsm_sync_info_t
*syncinfo
)
709 g_return_val_if_fail(dfsm
!= NULL
, -1);
710 g_return_val_if_fail(data
!= NULL
, -1);
711 g_return_val_if_fail(syncinfo
!= NULL
, -1);
712 g_return_val_if_fail(syncinfo
->data
!= NULL
, -1);
714 memdb_t
*memdb
= (memdb_t
*)data
;
716 cfs_debug("enter %s", __func__
);
718 dcdb_sync_info_t
*localsi
= (dcdb_sync_info_t
*)syncinfo
->data
;
720 guint count
= g_list_length(localsi
->updates
);
722 cfs_message("update complete - trying to commit (got %u inode updates)", count
);
724 if (!bdb_backend_commit_update(memdb
, localsi
->master
, localsi
->idx
, localsi
->updates
))
727 dcdb_sync_corosync_conf(memdb
, FALSE
);
736 dfsm_sync_info_t
*syncinfo
)
738 g_return_val_if_fail(dfsm
!= NULL
, -1);
739 g_return_val_if_fail(data
!= NULL
, -1);
740 g_return_val_if_fail(syncinfo
!= NULL
, -1);
741 g_return_val_if_fail(syncinfo
->data
!= NULL
, -1);
743 cfs_debug("enter %s", __func__
);
745 dcdb_sync_info_t
*localsi
= (dcdb_sync_info_t
*)syncinfo
->data
;
747 GList
*iter
= localsi
->updates
;
749 memdb_tree_entry_t
*te
= (memdb_tree_entry_t
*)iter
->data
;
750 memdb_tree_entry_free(te
);
751 iter
= g_list_next(iter
);
753 g_list_free(localsi
->updates
);
767 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
768 g_return_val_if_fail(csum
!= NULL
, FALSE
);
770 memdb_t
*memdb
= (memdb_t
*)data
;
772 g_return_val_if_fail(memdb
!= NULL
, FALSE
);
774 cfs_debug("enter %s %016" PRIX64
" %08X", __func__
, memdb
->root
->version
, memdb
->root
->mtime
);
776 g_mutex_lock (&memdb
->mutex
);
777 gboolean res
= memdb_compute_checksum(memdb
->index
, memdb
->root
, csum
, csum_len
);
778 g_mutex_unlock (&memdb
->mutex
);
780 cfs_debug("leave %s %016" PRIX64
" (%d)", __func__
, *( (uint64_t *) csum
), res
);
797 g_return_val_if_fail(dfsm
!= NULL
, -1);
798 g_return_val_if_fail(msg
!= NULL
, -1);
800 memdb_t
*memdb
= (memdb_t
*)data
;
802 g_return_val_if_fail(memdb
!= NULL
, -1);
803 g_return_val_if_fail(res_ptr
!= NULL
, -1);
807 int msg_result
= -ENOTSUP
;
809 if (!DCDB_VALID_MESSAGE_TYPE(msg_type
))
812 cfs_debug("process message %u (length = %zd)", msg_type
, msg_len
);
814 if (!cfs_is_quorate()) {
815 cfs_critical("received write while not quorate - trigger resync");
816 msg_result
= -EACCES
;
820 const char *path
, *to
, *buf
;
821 guint32 size
, offset
, flags
;
824 if (msg_type
== DCDB_MESSAGE_CFS_UNLOCK_REQUEST
||
825 msg_type
== DCDB_MESSAGE_CFS_UNLOCK
) {
826 msg_result
= 0; /* ignored anyways */
828 if (!dcdb_parse_unlock_request(msg
, msg_len
, &path
, &csum
))
832 memdb_tree_entry_t
*te
= memdb_getattr(memdb
, path
);
834 if (te
&& te
->type
== DT_DIR
&&
835 path_is_lockdir(path
) && memdb_tree_entry_csum(te
, cur_csum
) &&
836 (memcmp(csum
, cur_csum
, 32) == 0)) {
838 if (msg_type
== DCDB_MESSAGE_CFS_UNLOCK
) {
840 cfs_debug("got valid unlock message");
842 msg_result
= memdb_delete(memdb
, path
, nodeid
, msg_time
);
844 } else if (dfsm_lowest_nodeid(dfsm
)) {
846 cfs_debug("got valid unlock request message");
848 if (memdb_lock_expired(memdb
, path
, csum
)) {
849 cfs_debug("sending unlock message");
850 dcdb_send_unlock(dfsm
, path
, csum
, FALSE
);
854 memdb_tree_entry_free(te
);
856 } else if (msg_type
== DCDB_MESSAGE_CFS_WRITE
) {
858 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
859 &size
, &offset
, &flags
))
862 msg_result
= memdb_write(memdb
, path
, nodeid
, msg_time
,
863 buf
, size
, offset
, flags
);
865 if ((msg_result
>= 0) && !strcmp(path
, "corosync.conf"))
866 dcdb_sync_corosync_conf(memdb
, dfsm_nodeid_is_local(dfsm
, nodeid
, pid
));
868 } else if (msg_type
== DCDB_MESSAGE_CFS_CREATE
) {
870 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
871 &size
, &offset
, &flags
))
874 msg_result
= memdb_create(memdb
, path
, nodeid
, msg_time
);
876 if ((msg_result
>= 0) && !strcmp(path
, "corosync.conf"))
877 dcdb_sync_corosync_conf(memdb
, dfsm_nodeid_is_local(dfsm
, nodeid
, pid
));
879 } else if (msg_type
== DCDB_MESSAGE_CFS_MKDIR
) {
881 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
882 &size
, &offset
, &flags
))
885 msg_result
= memdb_mkdir(memdb
, path
, nodeid
, msg_time
);
887 } else if (msg_type
== DCDB_MESSAGE_CFS_DELETE
) {
889 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
890 &size
, &offset
, &flags
))
893 msg_result
= memdb_delete(memdb
, path
, nodeid
, msg_time
);
895 } else if (msg_type
== DCDB_MESSAGE_CFS_RENAME
) {
897 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
898 &size
, &offset
, &flags
))
901 msg_result
= memdb_rename(memdb
, path
, to
, nodeid
, msg_time
);
903 if ((msg_result
>= 0) && !strcmp(to
, "corosync.conf"))
904 dcdb_sync_corosync_conf(memdb
, dfsm_nodeid_is_local(dfsm
, nodeid
, pid
));
906 } else if (msg_type
== DCDB_MESSAGE_CFS_MTIME
) {
908 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
909 &size
, &offset
, &flags
))
912 /* Note: mtime is sent via offset field */
913 msg_result
= memdb_mtime(memdb
, path
, nodeid
, offset
);
919 *res_ptr
= msg_result
;
922 dfsm_set_errormode(dfsm
);
926 cfs_debug("leave %s (%d)", __func__
, res
);
931 cfs_critical("received unknown message type (msg_type == %u)", msg_type
);
938 static dfsm_callbacks_t dcdb_dfsm_callbacks
= {
939 .dfsm_deliver_fn
= dcdb_deliver
,
940 .dfsm_get_state_fn
= dcdb_get_state
,
941 .dfsm_process_state_update_fn
= dcdb_process_state_update
,
942 .dfsm_process_update_fn
= dcdb_process_update
,
943 .dfsm_commit_fn
= dcdb_commit
,
944 .dfsm_cleanup_fn
= dcdb_cleanup
,
945 .dfsm_checksum_fn
= dcdb_checksum
,
948 dfsm_t
*dcdb_new(memdb_t
*memdb
)
950 g_return_val_if_fail(memdb
!= NULL
, NULL
);
952 return dfsm_new(memdb
, DCDB_CPG_GROUP_NAME
, G_LOG_DOMAIN
,
953 DCDB_PROTOCOL_VERSION
, &dcdb_dfsm_callbacks
);