Commit Graph

82 Commits

Author SHA1 Message Date
Patrick Ohly c7a730ac08 local sync: fixed non-blocking recv()
recv() may return -1 and EAGAIN/EWOULDBLOCK, according to the man
page. That was treated as a fatal error instead of retrying, which
was the original intention.

For writev() it is less clear whether EAGAIN/EWOULDBLOCK need to be
handled. Let's catch them anyway.
2011-04-20 14:23:59 +02:00
Patrick Ohly e3ccba5d1c local sync: fixed potential NULL pointer read
The following code crashed if m_length was read after executing
the release() calls:
realloc(buffer.m_message.release(), buffer.m_message->m_length)

That's because release() resets the m_message pointer. It seems that
clang orders execution like that whereas gcc doesn't.
2011-04-20 14:20:46 +02:00
Patrick Ohly 467fdf70c8 local sync: fixed several potential bugs in transport
The main bug fix is for partial writes: the base address wasn't getting
updated, so the same data would have been sent multiple times. Not sure
whether this really occurred in practice.

fcntl() was called for random file descriptors due to a buffer
overflow. If a valid file descriptor was hit, the real user of it
might have gotten confused.

writev() was passed unitialized memory. Okay in this case (hole in struct),
but ugly in valgrind and easily fixed with memset().
2011-04-20 10:26:33 +02:00
Patrick Ohly 22e5783822 local sync: exceptions thrown in child process were not reported
Exceptions encountered in the child process were printed as [ERROR],
but not reported to the parent process and thus did not end up in the
final sync report.

Now they are, which makes finding the root cause of a failed local
sync a bit easier.
2011-04-19 13:54:09 +02:00
Patrick Ohly cac3ebfd9b local sync: better error message when URI is empty
The error message "@<context>/<source>: source not configured" becames
confusing when <source> is empty. Now "missing URI for one of the
sources" is printed instead.
2011-04-19 13:48:51 +02:00
Patrick Ohly ae8a09b1ce SyncConfig: "username/password" ambiguous, changed to "sync username/password"
The methods related to sync username/password were just called
get/setUsername/Password(), with additional check/savePassword()
methods. The savePassword() method clashed with a semantically
different method for arbitrary passwords (as pointed out by clang
2.9), so let's make it more clear that one set of methods specifically
is for the sync username/password.
2011-04-11 21:05:35 +02:00
Patrick Ohly 0969bd8ae1 local sync: use Timespec instead of time_t + time(NULL)
This makes the timeout handling resilient against system time changes
and increases accuracy.
2011-02-16 12:07:20 +01:00
Patrick Ohly 067a370f40 local sync: better abort handling
When the glib event loop is left because the D-Bus client has
requested an abort, the LocalTransportAgent should simply return a
"failed" status and let the caller handle the abort. The return code
of write/readMessage() must be able to convey that - extended from
boolean to an enum.

SyncContext did not do that correctly in server mode: the check for
abort must be done before giving up by throwing an exception.

The D-Bus test now checks that the right status is recorded (wasn't
the case earlier).
2011-02-16 11:55:43 +01:00
Patrick Ohly 0eb7baa89b local sync: allow running inside syncevo-dbus-server
Local sync inside syncevo-dbus-server must keep the main event
loop running, otherwise the D-Bus server would stop responding
to D-Bus calls while a sync runs.

This is tested as part of new test-dbus.py tests. They set up local
sync between two directories and then test syncing, timeout detection
when using the glib support code, and aborting via the D-Bus API
while a sync runs.

This testing depends on delaying the sync inside the child
process. Setting the SYNCEVOLUTION_LOCAL_CHILD_DELAY env variable
achieves that (might also be useful for interactive debugging). It is
set for those tests which need it via additional function properties,
similar to the older @timeout() mechanism, which now uses the
more general @property function decorator.
2011-02-15 16:50:39 +01:00
Patrick Ohly 0df76f7e09 LocalTransport: redo output redirection
Local sync suffered from the race condition that is solved by
LogRedirect::redoRedirection(). Use that...
2011-02-13 20:41:48 +01:00
Patrick Ohly 834bede321 LocalTransportAgent: implemented timeout handling
Timeouts for the SyncML message are detected on the server side.
No resending is possible, nor needed: this is a reliable local
transport after all, not HTTP.

The implementation uses select() and non-blocking sockets to time out
at the right time. While at it, it also sets CLOEXEC to ensure that
the pipes are not accidentally inherited by other child programs.
2011-02-09 15:33:20 +01:00
Patrick Ohly 40f84d7fc1 TransportAgent: simplified timeout API
Instead of allowing users of the API to register a callback
which can choose between aborting and time out, only accept
the timeout duration and always treat that as a timeout.

The advanced functionality wasn't used and the simplification
makes implementing the API easier.
2011-02-09 15:02:13 +01:00
Patrick Ohly dfb5cc5a09 local sync: override properties per config
Now the @context or @peer@context suffix in sync and source properties
on the command line can be used to configure both sides of the sync
differently.
2011-01-25 11:38:49 +01:00
Patrick Ohly 9d8485f1dd local sync: fixed internal communication issue with MaxMsgSize==0
When the settings had MaxMsgSize == 0, no buffer was allocated for
internal communication and syncing failed. Now the default is 1024
bytes.
2010-12-10 13:16:31 +01:00
Patrick Ohly c272727dc1 local sync: added target context to [INFO/DEBUG/...] prefix
Source names already contained the context in local sync, both in
parent and child process. But normal messages often did not
distinguish between parent and child, unless the message itself
explicitly remembered to include that information.

Now the child process puts its context into the [] prefix, like this:
[INFO @foobar] xyz...

For some messages this duplicates information, but better too often
than not often enough.
2010-12-10 13:16:31 +01:00
Patrick Ohly 8d728013f6 local sync: better integration into Client::Sync
When running as part of client-test, local sync now uses the "child"
directory inside the same per-test directory chosen by client-test.
2010-12-10 13:16:30 +01:00
Patrick Ohly aaeb556afb local sync: write child messages into <test>.log text file
When running client-test, the normal stdout text is copied into
a .log text file named after the currently running test. The output
of the child process should also go there.

This patch achieves that by being more selective about which loggers
in the stack of loggers it removes: LogDir must be removed because it
writes per-process Synthesis .html files, LoggerStdout must remain for
.log. The difference is abstracted away behind a new
Logger::isProcessSafe() method, which tells LocalTransportAgent whether
sharing the logger instance between processes is okay.
2010-12-10 13:16:23 +01:00
Patrick Ohly d3284d72a8 local sync: fixed a bug when overflowing the default message size
The code which resized the buffer for inter-process communication
forgot to update the buffer size, leading to a recv() with zero
size, leading to an error ("Operation not supported") and an aborted
sync.
2010-12-07 18:21:40 +01:00
Patrick Ohly 6a2b9750ec local sync: handle errors while receiving client report
If an error occurred while receiving the client report, that error
would trigger another attempt to receive the report, and so on, until
the stack was exhausted.

Now the m_statusFD is cleared before the only attempt to get the
report.
2010-12-01 12:32:47 +01:00
Patrick Ohly 51111bea95 LocalTransportAgent: added transmission of child's SyncReport
The SyncReport is transmitted via an additional socket pair. This is
necessary because the one for messages is shut down to notify the peer
of a premature shutdown.

The parent uses the information obtained from the SyncReport to update
its own status: first the error is logged (thus also setting the
"first error seen" part of the parent), then an exception with a bad child
status is thrown (interrupting anything the parent was doing and, if it
was the first error, setting the overall status of the sync).
2010-12-01 12:32:47 +01:00
Patrick Ohly b9b38520fa LocalTransportAgent: refactored read/write code
Moved the read/write code into subroutines. Added support for partial
writes.
2010-12-01 12:32:46 +01:00
Patrick Ohly 998e8a34eb local sync: share dumpData settings
Child uses parent's dumpData settings in local sync.
2010-12-01 12:32:46 +01:00
Patrick Ohly 6b4028275e LocalTransportAgent: fixed parent/child communication
There were some issues:
- not calling waitpid() caused zombies if the parent
  was a long-running process
- not closing the socket on the parent side caused
  the child to get stuck in error cases
- exit() has undesired side effects on the parent,
  use _exit() to just terminate the child without
  additional cleanup (more like fork/exec that way)

This patch also adds some debug output for tracking down
such issues.
2010-12-01 12:32:46 +01:00
Patrick Ohly 78276d4fed local sync: make more sync settings available to client
Temporarily setting --sync-property values only affects the server
side of local sync. This patch extends a hack which copies some
relevant values over into the client:
- do it sooner
- copy additional properties

A better way to set these properties on both sides of local sync is
needed.
2010-12-01 12:32:46 +01:00
Patrick Ohly e9e3c31ba5 local sync: avoid confusion about what data is changed
In local sync the terms "local" and "remote" (in SyncReport, "Data
modified locally") do not always apply and can be confusing. Replaced
with explicitly mentioning the context.

The source name also no longer is unique. Extended in the local sync
case (and only in that case) by adding a <context>/ prefix to the
source name.

Here is an example of the modified output:

$ syncevolution google
[INFO] @default/itodo20: inactive
[INFO] @default/addressbook: inactive
[INFO] @default/calendar+todo: inactive
[INFO] @default/memo: inactive
[INFO] @default/ical20: inactive
[INFO] @default/todo: inactive
[INFO] @default/file_calendar+todo: inactive
[INFO] @default/file_vcard21: inactive
[INFO] @default/vcard30: inactive
[INFO] @default/text: inactive
[INFO] @default/file_itodo20: inactive
[INFO] @default/vcard21: inactive
[INFO] @default/file_ical20: inactive
[INFO] @default/file_vcard30: inactive
[INFO] @google/addressbook: inactive
[INFO] @google/memo: inactive
[INFO] @google/todo: inactive
[INFO] @google/calendar: starting normal sync, two-way
Local data changes to be applied remotely during synchronization:
*** @google/calendar ***
                       after last sync | current data
               removed since last sync <
                                       > added since last sync
-------------------------------------------------------------------------------
BEGIN:VCALENDAR                          BEGIN:VCALENDAR
...
END:VCALENDAR                            END:VCALENDAR
-------------------------------------------------------------------------------

[INFO] @google/calendar: sent 1/2
[INFO] @google/calendar: sent 2/2
Local data changes to be applied remotely during synchronization:
*** @default/calendar ***
no changes

[INFO] @default/calendar: started
[INFO] @default/calendar: updating "created in Google, online"
[INFO] @default/calendar: updating "created in Google - mod2, online"
[INFO] @google/calendar: started
[INFO] @default/calendar: inactive
[INFO] @google/calendar: normal sync done successfully

Synchronization successful.

Changes applied during synchronization:
+---------------|-----------------------|-----------------------|-CON-+
|               |       @default        |        @google        | FLI |
|        Source | NEW | MOD | DEL | ERR | NEW | MOD | DEL | ERR | CTS |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|      calendar |  0  |  2  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |
|      disabled, 0 KB sent by client, 2 KB received                   |
|      item(s) in database backup: 3 before sync, 3 after it          |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|          start Mon Oct 25 10:03:24 2010, duration 0:13min           |
|               synchronization completed successfully                |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+

Data modified @default during synchronization:
*** @default/calendar ***
                           before sync | after sync
                   removed during sync <
                                       > added during sync
-------------------------------------------------------------------------------
BEGIN:VCALENDAR                          BEGIN:VCALENDAR
VERSION:2.0                              VERSION:2.0
...
END:VCALENDAR                            END:VCALENDAR
-------------------------------------------------------------------------------

pohly@pohly-mobl1:/tmp/syncevolution/src$
Synchronization successful.

Changes applied during synchronization:
+---------------|-----------------------|-----------------------|-CON-+
|               |        @google        |       @default        | FLI |
|        Source | NEW | MOD | DEL | ERR | NEW | MOD | DEL | ERR | CTS |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|      calendar |  0  |  0  |  0  |  0  |  0  |  2  |  0  |  0  |  0  |
|      two-way, 2 KB sent by client, 0 KB received                    |
|      item(s) in database backup: 2 before sync, 2 after it          |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|          start Mon Oct 25 10:03:24 2010, duration 0:13min           |
|               synchronization completed successfully                |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+

Data modified @google during synchronization:
*** @google/calendar ***
no changes
2010-12-01 12:32:45 +01:00
Patrick Ohly b15880e861 LocalTransportAgent: use SyncConfig::getContextName() utility function
Simplifies the code.
2010-12-01 12:32:45 +01:00
Patrick Ohly a9ee4e87ee local sync: disambiguate source names
During local sync names like "addressbook" are no longer unique,
because they may exist in both the local and the remote context. This
patch introduces a "display name" composed from context and source name,
like this: "@<context>/<source>" (@default/addressbook).

The context is only used if needed, which currently is the case during
a local sync.

Changing the SyncSourceBase::getName() result was also considered, but
several places expect this to be the name of the source inside its
context, so an explicit SyncSourceBase::getDisplayName() turned out
to be safer.
2010-12-01 12:32:44 +01:00
Patrick Ohly 783cad557e LocalTransportAgent: fixed interaction with peer config
Local sync with a "source-config" peer config for the sources
did not quite work right yet. This patch fixes several issues:
- double @ sign in source-config@<context>
- sync = disabled must be set explicitly before checking
  activated sources, because source-config@<context> may
  have some of these sources enabled (depends on persistent
  SyncSourceNodes)
- overriding the sync URL is not needed (transport agent already
  set explicitly) and harmful (original value needed by sources)
2010-12-01 12:32:44 +01:00
Patrick Ohly 8244b41b34 LocalTransportAgent: fixed compile error on MeeGo
AF_LOCAL was not found because the right header file
was not included explicitly.
2010-12-01 12:32:44 +01:00
Patrick Ohly 55ada103c4 SyncSourceParams: introduced context information
Backends like XMLRPC need information about URL, proxy and SSL
settings, etc. This can be done via source specific properties, like
evolutionsource, but this is not how this is normally done. It would
be nicer if the exising per-peer properties could be used. The goal is
that a normal peer configuration can be created from a template with
the necessary information to enable sources using that information.

This patch makes this possible by adding a context parameter to
SyncSourceParams:
     * @param    context     Additional non-source config settings.
     *                       When running as part of a normal sync, these are the
     *                       settings for the peer. When running in a local sync,
     *                       these settings come from the "source-config" peer
     *                       config inside the config context of the source.
     *                       Testing uses "source-config@client-test". On the
     *                       command line, this is the config chosen by the
     *                       user, which may or may not have peer-specific settings!

Note that this still doesn't solve the problem for XMLRPC to SyncML
peer sync, because in that case ("normal sync") the context will be
the one describing the peer. SyncURL is already used and proxy
settings might not match.

The XMLRPC backends therefore was not changed and continues to use
evolutionsource.
2010-12-01 12:32:43 +01:00
Patrick Ohly c2f57528a0 local sync: added sanity checks for syncURL (BMC #712)
Don't allow sync inside same context, too easy to configure incorrectly.
Also don't allow referencing a peer (leads to incorrect session dirs
in client and cannot override peer files).
2010-12-01 12:32:43 +01:00
Patrick Ohly eba8a74779 support local sync (BMC #712)
Local sync is configured with a new syncURL = local://<context> where
<context> identifies the set of databases to synchronize with. The
URI of each source in the config identifies the source in that context
to synchronize with.

The databases in that context run a SyncML session as client. The
config itself is for a server. Reversing these roles is possible by
putting the config into the other context.

A sync is started by the server side, via the new LocalTransportAgent.
That agent forks, sets up the client side, then passes messages
back and forth via stream sockets. Stream sockets are useful because
unexpected peer shutdown can be detected.

Running the server side requires a few changes:
- do not send a SAN message, the client will start the
  message exchange based on the config
- wait for that message before doing anything

The client side is more difficult:
- Per-peer config nodes do not exist in the target context.
  They are stored in a hidden .<context> directory inside
  the server config tree. This depends on the new "registering nodes
  in the tree" feature. All nodes are hidden, because users
  are not meant to edit any of them. Their name is intentionally
  chosen like traditional nodes so that removing the config
  also removes the new files.
- All relevant per-peer properties must be copied from the server
  config (log level, printing changes, ...); they cannot be set
  differently.

Because two separate SyncML sessions are used, we end up with
two normal session directories and log files.

The implementation is not complete yet:
- no glib support, so cannot be used in syncevo-dbus-server
- no support for CTRL-C and abort
- no interactive password entry for target sources
- unexpected slow syncs are detected on the client side, but
  not reported properly on the server side
2010-12-01 12:32:43 +01:00