aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-server.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/src/mds-server.c b/src/mds-server.c
index 7bd49e1..4438397 100644
--- a/src/mds-server.c
+++ b/src/mds-server.c
@@ -334,6 +334,12 @@ int main(int argc_, char** argv_)
char** reexec_args;
char** reexec_args_;
char reexec_arg[24];
+ size_t list_size;
+ size_t map_size;
+ size_t list_elements;
+ size_t msg_size;
+ ssize_t node;
+
#if INT_MAX > UINT64_MAX
# error It seems int:s are really big, you might need to increase the size of reexec_arg.
#endif
@@ -348,26 +354,93 @@ int main(int argc_, char** argv_)
pthread_cond_wait(&slave_cond, &slave_mutex);
pthread_mutex_unlock(&slave_mutex);
- /* Marshal the state of the server. */ /* TODO marshal all data. */
- state_n = 2 * sizeof(int) + 1 * sizeof(sig_atomic_t);
- state_buf = alloca(state_n);
+ /* Marshal the state of the server. */
+ list_size = linked_list_marshal_size(&client_list);
+ map_size = fd_table_marshal_size(&client_map);
+ list_elements = 0;
+ msg_size = 0;
+ for (node = client_list.edge;; list_elements++)
+ {
+ mds_message_t message;
+ if ((node = client_list.next[node]) == client_list.edge)
+ break;
+ message = ((client_t*)(void*)(client_list.values[node]))->message;
+ msg_size += mds_message_marshal_size(&message, 1);
+ }
+ state_n = sizeof(ssize_t) + 2 * sizeof(int) + 2 * sizeof(size_t);
+ state_n *= list_elements;
+ state_n += msg_size;
+ state_n += 2 * sizeof(int) + 1 * sizeof(sig_atomic_t) + 3 * sizeof(size_t);
+ state_buf = malloc(state_n);
state_buf_ = state_buf;
((int*)state_buf_)[0] = MDS_SERVER_VARS_VERSION;
((int*)state_buf_)[1] = socket_fd;
state_buf_ += 2 * sizeof(int) / sizeof(char);
((sig_atomic_t*)state_buf_)[0] = running;
state_buf_ += 1 * sizeof(sig_atomic_t) / sizeof(char);
+ ((size_t*)state_buf_)[0] = list_size;
+ ((size_t*)state_buf_)[1] = map_size;
+ ((size_t*)state_buf_)[2] = list_elements;
+ state_buf_ += 3 * sizeof(size_t) / sizeof(char);
+ for (node = client_list.edge;;)
+ {
+ size_t value_address;
+ client_t* value;
+ if ((node = client_list.next[node]) == client_list.edge)
+ break;
+ value_address = client_list.values[node];
+ value = (client_t*)(void*)value_address;
+ msg_size = mds_message_marshal_size(&(value->message), 1);
+ ((size_t*)state_buf_)[0] = value_address;
+ ((ssize_t*)state_buf_)[1] = value->list_entry;
+ ((size_t*)state_buf_)[2] = msg_size;
+ state_buf_ += 3 * sizeof(size_t) / sizeof(char);
+ ((int*)state_buf_)[0] = value->socket_fd;
+ ((int*)state_buf_)[1] = value->open;
+ state_buf_ += 2 * sizeof(int) / sizeof(char);
+ mds_message_marshal(&(value->message), state_buf_, 1);
+ state_buf_ += msg_size / sizeof(char);
+ }
if (pipe(pipe_rw) < 0)
goto reexec_fail;
- errno = 0;
while (state_n > 0)
{
+ errno = 0;
wrote = write(pipe_rw[1], state_buf, state_n);
if (errno && (errno != EINTR))
goto reexec_fail;
state_n -= (size_t)(wrote < 0 ? 0 : wrote);
state_buf += (size_t)(wrote < 0 ? 0 : wrote);
}
+ free(state_buf);
+ state_buf = malloc(list_size);
+ if (state_buf == NULL)
+ goto reexec_fail;
+ linked_list_marshal(&client_list, state_buf);
+ while (list_size > 0)
+ {
+ errno = 0;
+ wrote = write(pipe_rw[1], state_buf, list_size);
+ if (errno && (errno != EINTR))
+ goto reexec_fail;
+ list_size -= (size_t)(wrote < 0 ? 0 : wrote);
+ state_buf += (size_t)(wrote < 0 ? 0 : wrote);
+ }
+ free(state_buf);
+ state_buf = malloc(map_size);
+ if (state_buf == NULL)
+ goto reexec_fail;
+ fd_table_marshal(&client_map, state_buf);
+ while (map_size > 0)
+ {
+ errno = 0;
+ wrote = write(pipe_rw[1], state_buf, map_size);
+ if (errno && (errno != EINTR))
+ goto reexec_fail;
+ map_size -= (size_t)(wrote < 0 ? 0 : wrote);
+ state_buf += (size_t)(wrote < 0 ? 0 : wrote);
+ }
+ free(state_buf);
close(pipe_rw[1]);
/* Re-exec the server. */
@@ -389,6 +462,8 @@ int main(int argc_, char** argv_)
reexec_fail:
perror(*argv);
+ if (state_buf != NULL)
+ free(state_buf);
close(pipe_rw[0]);
close(pipe_rw[1]);
/* Returning non-zero is important, otherwise the server cannot