Commit graph

3547 commits

Author SHA1 Message Date
Patrick Ohly
a882bc7e90 glib: SYNCEVO_GLIB_CALL_SYNC() must use GRunWhile()
Like everything else that waits for a certain event on the main loop,
SYNCEVO_GLIB_CALL_SYNC() should also better use GRunWhile(). This is
necessary to be usable in threads.
2013-09-04 11:05:47 +02:00
Patrick Ohly
b7fa64f15c signon: revert accidental inclusion in master branch
The code wasn't ready and got pushed as part of some other change.
2013-08-02 22:02:03 +02:00
Patrick Ohly
c0212c4585 PBAP: add support for obexd 0.48
obexd 0.48 is almost the same as obexd 0.47, except that it dropped
the SetFilter and SetFormat methods in favor of passing a Bluex 5-style
filter parameter to PullAll.

SyncEvolution now supports 4, in words, four different obexd
APIs. Sigh.
2013-08-02 16:37:01 +02:00
Patrick Ohly
a6b8eea548 signon: README and example Google accounts files
The README explains how to use Google CalDAV/CardDAV together with
the example accounts config files.
2013-08-02 13:17:02 +02:00
Patrick Ohly
f0254a30bb singon: new backend using libgsignond-glib + libaccounts-glib
The code works with gSSO (https://01.org/gsso). With some tweaks to
the configure check and some ifdefs it probably could be made to work
Ubuntu Online Accounts.

The code depends on an account accessible via libaccounts-glib which
has a provider and and (optionally) services enabled for that
provider. It is not necessary that the account already has a signon
identity ID, the backend will create that for the provider (and thus
shared between all services) if necessary.

Therefore it is possible to use the ag-tool to create and enable the
account and services. Provider and service templates are in the next
commit.
2013-08-02 13:16:11 +02:00
Patrick Ohly
3de6da6022 WebDAV: support OAuth2
If given an AuthProvider which can handle OAuth2, then OAuth2 is
used instead of plain username/password authentication.

Obtaining the OAuth2 token must be done at a point where we can still
abort the request. If obtaining the token fails, then this should be
considered a fatal error which aborts scanning for resources. Other
errors cause the current URL to be skipped while scanning continues.

This commit moves the "execute request" functionality back into the
Neon::Session class, because that is where most of the logic (retry
request?) and state is (access tokens which persist across requests).
2013-08-02 13:15:33 +02:00
Patrick Ohly
7fdd878bc1 config: add identity provider registry
Similar to the RegisterSyncSource concept, but trimmed down:
- virtual method creates instances
- keys have to be unique
2013-08-02 13:15:27 +02:00
Patrick Ohly
03efa0c44d config: introduce AuthProvider
AuthProvider is the instance created by specific IdentityProvider
backends which then hands out username/password credentials or OAuth2
bearer tokens.
2013-08-02 13:15:27 +02:00
Patrick Ohly
80e68a747a config: first step towards modular identity providers
Let the conversion to username+password be handled by the
IdentityProvider module.
2013-08-02 13:15:27 +02:00
Patrick Ohly
97863d3b7e config: selectively resolve username during indirect credential lookup
The real username is only relevant when running a sync. When looking
at a config with a D-Bus client like the GTK UI, the username should
always be "id:<config>", to avoid accidentally removing the
indirection, while the password should be the real one, to allow the
user to edit like he normally would with passwords stored in a
keyring.

To achive this, overriding the username must be suppressed when
resolving as part of the D-Bus config API. While at it, move the
entire "iterate over properties" into a common utility function in
PasswordConfigProperty.
2013-08-02 13:15:26 +02:00
Patrick Ohly
c3fdf439da SyncConfig: implement "id" handling for reading and writing credentials
save/checkPassword both know how to handle the "id" provider now.
2013-08-02 13:15:26 +02:00
Patrick Ohly
d2a4164668 SyncConfig: allow sharing file config tree between configs
A SHARED_LAYOUT config tree caches config nodes. Allow a second config
to use those same nodes as an already existing config. This will be
useful in combination with indirect password lookup, because then the
credentials can be stored as temporary property values and be reused
when used multiple times in a process (for example, by CardDAV and by
CalDAV).
2013-08-02 13:15:20 +02:00
Patrick Ohly
d9f87251c0 SyncConfig: simplify password API
In practice, the methods are always called for a specific SyncConfig.
Passing that allows removing several other parameters and, more
importantly, also grants access to the config and through that other
configs. This will be needed for the indirect credential lookup.
2013-08-02 13:15:14 +02:00
Patrick Ohly
1131379cc5 SyncConfig: allow access to ConfigTree
This will be needed to access other configs in the indirect password
lookup.
2013-08-02 13:15:13 +02:00
Patrick Ohly
059bb0bd6f SyncSourceConfig: remove obsolete password methods
Not used, the per-source password operations are done via the
ConfigProperty interface.
2013-08-02 13:15:13 +02:00
Patrick Ohly
5ff97dea44 config: user name -> identity
"username", "proxyUsername" and "databaseUser" used to be simply a
string containing the name of the respective user or (in the case of
the ActiveSync backend) the account ID in gconf.

Now it is also possible to provide credentials (username + password)
indirectly: when any of these properties is set to "id:<config name>",
then the "username/password" properties in that config are used
instead. This is useful in particular with WebDAV, where credentials
had to be repeated several times (target config, in each database when
used as part of SyncML) or when using a service which requires several
configs (Google via SyncML and CalDAV).

For user names which contain colons, the new "user:<user name>" format
must be used. Strings without colons are assumed to be normal user
names.

This commit changes the SyncConfig APIs for this extension. More work
is needed to make the indirect lookup via "id" functional.
2013-08-02 13:15:13 +02:00
Patrick Ohly
56ac0812a4 SyncConfig: remove obsolete caching of passwords
Passwords are cached after the initial check as temporary property
values. The explicit string members are obsolete and can be removed
together with the code using them.
2013-08-02 13:15:13 +02:00
Patrick Ohly
193ef1e534 glib: SYNCEVO_GLIB_CALL_SYNC() must use GRunWhile()
Like everything else that waits for a certain event on the main loop,
SYNCEVO_GLIB_CALL_SYNC() should also better use GRunWhile(). This is
necessary to be usable in threads.
2013-08-02 13:15:13 +02:00
Patrick Ohly
0a8b3f1f48 D-Bus server: password not stored in GNOME keyring or KWallet (FDO #66110)
When clients like the GTK sync-ui stored a password, it was always
stored as plain text in the config.ini file by the
syncevo-dbus-server. The necessary code for redirecting the password
storage in a keyring (GNOME or KWallet) simply wasn't called in that
case.

The command line tool, even when using the D-Bus server to run the
operation, had the necessary code active and thus was not affected.
2013-08-02 13:15:13 +02:00
Patrick Ohly
8bc48fd7d8 PBAP: compile fix for "PBAP: transfer data inside ReadItemAsKey"
uint16 happened to work when compiling with a recent GNOME stack, but
without that uint16 is not defined. The right approach is to use
stdint.h and uint16_t.
2013-07-25 11:19:03 +02:00
Guido Günther
85fca61913 build: use top_builddir instead of builddir
when building syncevo-local-sync. Maemo's old automake doesn't now
about builddir.

This only fixes the one occurence relevant to Maemo.
2013-07-12 16:18:12 +02:00
Patrick Ohly
c16f1b0756 sync: avoid maintaining suspend/resume meta data during ephemeral sync
Both maintaining the map items inside the Synthesis engine and storing
them in .ini hash config nodes inside SyncEvolution are fairly heavy
operations which are not needed at all during an ephemeral sync (= no
meta data stored, done by the PIM Manager when triggering a pure PBAP
sync).

Using the new Synthesis CA_ResumeSupported DB capability it is
possible to suppress these operations without having to fiddle with
the Synthesis DB API that SyncEvolution provides. To make it possible
at the DB layer to detect that the meta data is not needed, the
ConfigNode passed to it must be marked as volatile.

This change sped up a sync with 10000 unmodified, known items from 38s
to 23s.
2013-07-12 11:44:39 +02:00
Patrick Ohly
5aec08d12c SyncSourceConfig: cache synthesisID
The synthesisID value is required for each Synthesis source progress
event, which can be fairly frequent (more than one per item). Instead
of going down to the underlying .ini config node each time, cache the
value in the SyncSourceConfig layer.
2013-07-12 11:44:39 +02:00
Patrick Ohly
a05197891f sync: reduce D-Bus traffic
Syncing was slowed down by fowarding all log messages from the local
sync helper to its parent and from the D-Bus helper to
syncevo-dbus-server. Quite often, the log messages then were simply
discarded by the recipient. To speed up syncing, better filter at the
source.

The syncevo-dbus-helper is told which messages are relevant by
forwarding the syncevo-dbus-server "D-Bus log level" command line
setting to the helper process as part of its argv parameters.

The synevo-local-sync helper applies its own log level now also to the
messages sent to the parent. This ensures that messages stored in the
client log also show up in the parent log (unless the parent has more
restrictive settints, which is uncommon) and that INFO/SHOW messages
still reach the user.
2013-07-12 11:44:39 +02:00
Patrick Ohly
b34d56482e sync: less verbose output, shorter runtime
For each incoming change, one INFO line with "received x[/out of y]"
was printed, immediately followed by another line with total counts
"added x, updated y, removed z". For each outgoing change, a "sent
x[/out of y]" was printed.

In addition, these changes were forwarded to the D-Bus server where a
"percent complete" was calculated and broadcasted to clients. All of
that caused a very high overhead for every single change, even if the
actual logging was off. The syncevo-dbus-server was constantly
consuming CPU time during a sync when it should have been mostly idle.

To avoid this overhead, the updated received/sent numbers that come
from the Synthesis engine are now cached and only processed when done
with a SyncML message or some other event happens (whatever happens
first).

To keep the implementation simple, the "added x, updated y, removed z"
information is ignored completely and no longer appears in the output.

As a result, syncevo-dbus-server is now almost completely idle during
a running sync with no log output. Such a sync involving 10000 contacts
was sped up from 37s to 26s total runtime.
2013-07-12 11:43:40 +02:00
Patrick Ohly
f2378b7909 ForkExec: allow passing arguments to helper
The optional args array will be used when executing the helper
executable.
2013-07-11 11:40:51 +02:00
Patrick Ohly
0a3ec71e92 PIM testing: include testcase from FDO #66618
Ordering of 鳥 = niǎo before 女性 = nǚ xìng depends on the right
env variables. It works in this test.
2013-07-10 13:08:02 +02:00
Patrick Ohly
dc35d87dec D-Bus: better logging of server stub transport exceptions
Use SE_THROW() instead of "throw" because we want the error being
logged in the current sync log.
2013-07-10 13:08:02 +02:00
Patrick Ohly
7059459768 D-Bus: allow catching syncevo-dbus-helper in valgrind debugger
Set SYNCEVOLUTION_DBUS_HELPER_VGDB=1, add --vgdb-error=1 --vgdb=yes
to VALGRIND_ARGS, run test, wait for vgdb message in valgrind*.out files,
attach as instructed.

With --vgdb-error=0, all processes block during startup, waiting for
the debugger to attach.
2013-07-10 13:08:02 +02:00
Patrick Ohly
1538b89b36 PBAP: transfer data inside ReadItemAsKey
The previous attempt with concurrent reading while listing IDs did not
work, that listing must complete before the SyncML client contacts the
server. What works is transfering and parsing after the engine starts
to ask for the actual data.

For that we need to list IDs in advance. We use GetSize() for that.

If contacts get deleted while we read, getting the data for the
contacts at the end of the range will fail with 404, which is
understood by the Synthesis engine and leads to ignoring the ID, as
intended.

If contacts get added while we read, we will ignore them even if they
happen to be in the result of PullAll. The next sync will include
them.
2013-07-10 13:08:02 +02:00
Patrick Ohly
19aeba2029 PIM: use incremental sync for PBAP by default (FDO #59551)
When doing a PBAP sync, PIM manager asks the D-Bus sync helper to set
its SYNCEVOLUTION_PBAP_SYNC to "incremental". If the env variable
is already set, it does not get overwritten, which allows overriding
this default.
2013-07-10 13:08:02 +02:00
Patrick Ohly
7bd8a187d2 PIM testing: more flexible exclusion of empty vcard
Don't depend on order of properties, something else was seen.
2013-07-10 13:08:02 +02:00
Patrick Ohly
ddc1e53b0c PBAP: incremental sync (FDO #59551)
Depending on the SYNCEVOLUTION_PBAP_SYNC env variable, syncing reads
all properties as configured ("all"), excludes photos ("text") or
first text, then all ("incremental").

When excluding photos, only known properties get requested. This
avoids issues with phones which reject the request when enabling
properties via the bit flags. This also helps with
"databaseFormat=^PHOTO".

When excluding photos, the vcard merge script as used by EDS ensures
that existing photo data is preserved. This only works during a slow
sync (merge script not called otherwise, okay for PBAP because it
always syncs in slow sync) and EDS (other backends do not use the
merge script, okay at the moment because PIM Manager is hard-coded to
use EDS).

The PBAP backend must be aware of the PBAP sync mode and request a
second cycle, which again must be a slow sync. This only works because
the sync engine is aware of the special mode and sets a new session
variable "keepPhotoData". It would be better to have the PBAP backend
send CTCap with PHOTO marked as not supported for text-only syncs and
enabled when sending PHOTO data, but that is considerably harder to
implement (CTCap cannot be adjusted at runtime).

beginSync() may only ask for a slow sync when not already called
for one. That's what the command line tool does when accessing
items. It fails when getting the 508 status.

The original goal of overlapping syncing with download has not been
achieved yet. It turned out that all item IDs get requested before
syncing starts, which thus depends on downloading all items in the current
implementation. Can be fixed by making up IDs based on the number of
existing items (see GetSize() in PBAP) and then downloading later when
the data is needed.
2013-07-10 13:08:02 +02:00
Patrick Ohly
309bed01e1 SyncSource: avoid ERROR logging for 508 status code
Returning a 508 status from beginSync() via a StatusException is
valid, this should only be logged by the originator if it deems that
an error.
2013-07-10 13:08:02 +02:00
Patrick Ohly
6d3b1cf64b EDS: update PHOTO+GEO during slow sync, avoid rewriting PHOTO file
If PHOTO and/or GEO were the only modified properties during a slow
sync, the updated item was not written into local storage because
they were marked as compare="never" = "not relevant".

For PHOTO this was intentional in the sample config, with the
rationale that local storages often don't store the data exactly as
requested. When that happens, comparing the data would lead to
unnecessary writes. But EDS and probably all other local SyncEvolution
storages (KDE, file) store the photo exactly as requested, so not
considering changes had the undesirable effect of not always writing
new photo data.

For GEO, ignoring it was accidental.

A special merge script handles EDS file:// photo URIs. When the
loosing item has the data in a file and the winning item has binary
data, the data in the file may still be up-to-date, so before allowing
MERGEFIELDS() to overwrite the file reference with binary data and
thus forcing EDS to write a new file, check the content. If it
matches, use the file reference in both items.
2013-07-10 13:08:02 +02:00
Patrick Ohly
50c06bbe61 EDS contacts: read-ahead cache
Performance is improved by requesting multiple contacts at once and
overlapping reading with processing. On a fast system (SSD, CPU fast
enough to not be the limiting factor), testpim.py's testSync takes 8
seconds for a "match" sync where 1000 contacts get loaded and compared
against the same set of contacts. Read-ahead with only 1 contact per
query speeds that up to 6.7s due to overlapping IO and
processing. Read-ahead with the default 50 contacts per query takes
5.5s. It does not get much faster with larger queries.

While returning items from one cache populated with a single
e_book_client_get_contacts() call, another query is started to overlap
processing and loading.

To achieve efficient read-ahead, the backend relies on the hint given
to it via setReadAheadOrder(). As soon as it detects that a contact is
not the next one according to that order, it switches back to reading
one contact at a time. This happens during the write phase of a sync
where the Synthesis engine needs to read, update, and write back
changes based on updates sent by the peer.

Cache statistics show that this works well for --print-items, --export
and slow syncs.

Writing into the database must invalidate the corresponding cached
contact. Otherwise the backup operation after a sync may end up
reading stale data.
2013-07-10 13:07:53 +02:00
Patrick Ohly
7d12c0a586 read-ahead: tell SyncSource about the upcoming read accesses
Trying to predict in the SyncSource which items will be needed is
hard. It depends what the item is retrieved for (sync or
backup/printing) and on the sync mode (during a sync).

Instead of guessing, better have the user of the source tell the
source in advance what it will read. In most cases this is cheap
because it does not involve copying of items luids ("read all items",
"read new or modified items"). The source then can use its own internal
mechanisms to figure out what that means.

Only extracting specific items specified on the command line and the
backup operation must explicitly pass an ordered list of luids. For
the sake of simplicity, do that in a std::vector even though it
involves copying.
2013-07-10 13:07:44 +02:00
Patrick Ohly
81fdf67437 glib: allow other threads to check something after each main loop iteration
The
  while (<something>) g_main_context_iterate(NULL, true);
pattern only works in the main thread. As soon as multiple
threads are allowed to process events, race conditions occur,
as described before.

But the pattern is useful, so support it in all threads by
shifting the check into the main thread, which will then notify
other threads via a condition variable when something changes.
2013-07-10 13:07:35 +02:00
Patrick Ohly
ce1809d811 Threading: add Cond class
A thin wrapper around GMutex, initializes the condition variable
automatically.
2013-07-05 17:44:20 +02:00
Patrick Ohly
8ba5b42b92 Threading: fix Dyn*Mutex
gcc complained about the "protected" m_mutex access. Apparently
it did not realize that the access was to a base class. An explicit
get() solves that. Another way to get the pointer is a type cast.
2013-07-05 17:44:20 +02:00
Patrick Ohly
a5fd9df29d PBAP: refactor PbapSyncSource, asyncronous transfer, report items immediately
Derive from SyncSource and SyncSourceSession directly instead of going
through TrackingSyncSource. This allows removing several dummy methods
that we have to implement for TrackingSyncSource and allows
reporting existing items incrementally, instead of having to load all
of them at once for the old listAllItems().

Contacts are now already reported to the engine while their transfer
still runs. That depends on monitoring the temporary file, remapping
the larger file and continuing parsing where the previous parsing
stopped.

This only works with obexd 0.47 and obexd from Bluez 5, because it
depends on the temporary file interface. The older PullAll did not
return any data until it had downloaded everything.

Because it isn't known when the contact data will be needed, the backend
still maintains the mapping from ID to vCard data for all contacts seen
in the current session. Because that memory is backed by a temporary file
system, unused memory can be swapped out (and in) well by the OS.

If the file is in a ram-based temp file system, then it may also not
matter at all that the file gets mapped multiple times.
2013-07-05 17:44:20 +02:00
Patrick Ohly
37c29253cf GErrorCXX: add take()
The other methods always make a copy of the GError. The new take()
method takes over ownership. Use in combination with g_error_new().
2013-07-05 17:44:20 +02:00
Patrick Ohly
55c0806800 command line: execute --export and --print-items while the source is still reading
Instead of reading all item IDs, then iterating over them, process
each new ID as soon as it is available. With sources that support
incremental reading (only the PBAP source at the moment) that provides
output sooner and is a bit more memory efficient.
2013-07-05 17:44:20 +02:00
Patrick Ohly
e6c07b32b9 TmpFile: add moreData() and remove()
remove() is useful when want to continue using the file but also want
to ensure that it gets deleted when we crash.

moreData() can be used to determine if the file has grown since the
last time that map() was called. In other words, it supports
processing data while obexd still writes into the file.
2013-07-05 17:44:20 +02:00
Patrick Ohly
d0626ea46c GDBus GIO: support int64_t and uint64_t
The dbus_traits for them were simply missing.
2013-07-05 17:44:20 +02:00
Patrick Ohly
4bf2adbe25 GDBus GIO: avoid unnecessary case-insentive type comparison.
The type is already lower-case on both sides, so there's no
need for the case-insensitive comparison.
2013-07-05 17:44:20 +02:00
Patrick Ohly
25f24387c3 PBAP: fix support for obexd == 0.47, break 0.48
The previous commit "PBAP: fix support for obexd >= 0.47 and < Bluez 5"
made the backend work with obexd 0.48 and broke it with 0.47. That's because
there was another API change between 0.47 and 0.48, which wasn't known
at the time of that commit.

SyncEvolution now works with 0.47 and does not work with 0.48. This choice
was made because 0.47 supports the file-based data transfer (same as in Bluez 5
and thus useful for testing when Bluez 5 is not available) and 0.47 still
compiles against older Bluez versions (which makes it easier to use than 0.48).
2013-07-05 17:44:10 +02:00
Patrick Ohly
eca4dcb4b5 SuspendFlags: make it thread-safe
A new internal recursive mutex protects data that may get accessed
from different threads. It's recursive because callbacks may need to
lock it again.
2013-07-05 17:44:10 +02:00
Patrick Ohly
0c63a4f7f0 D-Bus testing: support git glib/gobject bindings
More recent GNOME Python bindings are provided by gobject
introspection. The traditional gobject/glib modules no
longer exist.

The API is similar enough that we just need to adapt importing: if
importing the normal modules fails, try importing from gi.repository
instead.
2013-07-05 17:44:10 +02:00
Patrick Ohly
dfd0bc29af EDS contacts: avoid unnecessary DB writes during slow sync due to FILE-AS
EDS 3.8 sets X-EVOLUTION-FILE-AS to "last, first" when a contact is
created without it. This leads again to unnecessary DB updates because
the incoming item that the engine works with doesn't have that field
set.

To mitigate that issue, set FILE_AS (renamed to make the field name
valid in a script) like EDS would do during writing.

The downside is that all incoming items now have FILE_AS set, which
will overwrite a locally stored copy of that property even if the peer
did not store X-EVOLUTION-FILE-AS. Previously, as tested by
testExtension, the local value was preserved. There is no good solution
that works for both use cases, so allow X-EVOLUTION-FILE-AS to get lost
and relax the test.
2013-07-05 17:44:10 +02:00