Commit Graph

279 Commits

Author SHA1 Message Date
Patrick Ohly 04f11b422e source -> datastore rename, improved terminology
The word "source" implies reading, while in fact access is read/write.
"datastore" avoids that misconception. Writing it in one word emphasizes
that it is single entity.

While renaming, also remove references to explicit --*-property
parameters. The only necessary use today is "--sync-property ?"
and "--datastore-property ?".

--datastore-property was used instead of the short --store-property
because "store" might be mistaken for the verb. It doesn't matter
that it is longer because it doesn't get typed often.

--source-property must remain valid for backward compatility.

As many user-visible instances of "source" as possible got replaced in
text strings by the newer term "datastore". Debug messages were left
unchanged unless some regex happened to match it.

The source code will continue to use the old variable and class names
based on "source".

Various documentation enhancements:
  Better explain what local sync is and how it involves two sync
  configs. "originating config" gets introduces instead of just
  "sync config".

  Better explain the relationship between contexts, sync configs,
  and source configs ("a sync config can use the datastore configs in
  the same context").

  An entire section on config properties in the terminology
  section. "item" added (Todd Wilson correctly pointed out that it was
  missing).

  Less focus on conflict resolution, as suggested by Graham Cobb.

  Fix examples that became invalid when fixing the password
  storage/lookup mechanism for GNOME keyring in 1.4.

  The "command line conventions", "Synchronization beyond SyncML" and
  "CalDAV and CardDAV" sections were updated. It's possible that the
  other sections also contain slightly incorrect usage of the
  terminology or are simply out-dated.
2014-07-28 15:29:41 +02:00
Patrick Ohly 834c1e7a6b ephemeral sync: don't write binfile client files (FDO #55921)
When doing PBAP caching, we don't want any meta data written because
the next sync would not use it anyway. With the latest libsynthesis
we can configure "/dev/null" as datadir for the client's binfiles and
libsynthesis will avoid writing them.

The PIM manager uses this for PBAP syncing automatically. For testing
it can be enabled by setting the SYNCEVOLUTION_EPHEMERAL env variable.
2014-07-23 10:48:19 +02:00
Patrick Ohly 8e333f0a46 glib: avoid deprecated g_type_init and g_thread_init
Calling them triggers warnings with newer glib which are fatal
when compiling with -Werror.
2014-07-23 10:48:19 +02:00
Patrick Ohly de8461f802 code restructing: Exception, throwError()
Raising exceptions via throwError() looses the original source code
location information. Fixing that by explicitly passing that
information as additional parameter, created with the preprocessor
macro SE_HERE.

Several files included the complex SyncContext.h only because needed
throwError(). A better place for the revised implementation is the
Exception class which used to be in util.h, now Exception.h.

Simplifying the include statements exposed indirect include
dependencies and removed "using namespace std" from the compilation of
some source files which happened to rely on it. We want to get rid of
that name space polution, so fix the code instead of adding it back.
2014-05-02 16:43:52 +02:00
Patrick Ohly fc8caadd8d PBAP: Suspend/ResumeSync() (FDO #72112)
The information that the sync is freezing is now also handed down to
the transport and all sources. In the case of PBAP caching, the local
transport notifies the child where the PBAP source then uses Bluez
5.15 Transfer1.Suspend/Resume to freeze/thaw the actual OBEX transfer.

If that fails (for example, not implemented because Bluez is too old
or the transfer is still queueing), then the transfer gets cancelled
and the entire sync fails. This is desirable for PBAP caching and
Bluetooth because a failed sync can easily be recovered from (just
start it again) and the overall goal is to free up Bluetooth bandwidth
quickly.
2014-04-01 16:45:09 +02:00
Patrick Ohly 9c3601809d PIM: Suspend/ResumeSync() (part of FDO #72112)
Currently implements the new API by stopping to consume data on the
local side of the sync. The Bluetooth transfer on the remote side
continues to run and isn't even notified about the suspend; need a new
obexd API to also suspend that and then notify the remote side when we
want it to do that.
2014-04-01 16:45:09 +02:00
Patrick Ohly 3c01a1ebf6 PIM: enhanced progress notifications (FDO #72114)
This adds GetPeerStatus() and "progress" events.

To detect DB changes as they happen, the SyncSource operations are
monitored. Upon entry, a counter gets increased and transmitted
through to the PIM manager in syncevo-dbus-server using extended
SourceProgress structs (only visible internally - public API must not
be extended!). This will count operations which fail and count those
twice which get resumed, so the counts will be too high
occasionally. That is in line with the API definition; because it is
not exact, the API only exposes a "modified" flag.

Progress is reported based on the "item received" Synthesis event and
the total item count. A modified libsynthesis is needed where the
SyncML binfile client on the target side of the local sync actually
sends the total item count (via NumberOfChanges). This cannot be done
yet right at the start of the sync, only the second SyncML message
will have it. That is acceptable, because completion is reached very
quickly anyway for syncs involving only one message.

At the moment, SyncContext::displaySourceProgress() holds back "item
received" events until a different event needs to be emitted. Progress
reporting might get more fine-grained when adding allowing held back
events to be emitted at a fixed rate, every 0.1s. This is not done yet
because it seems to work well enough already.

For testing and demonstration purposes, sync.py gets command line
arguments for setting progress frequency and showing progress either
via listening to signals or polling.
2014-04-01 16:45:09 +02:00
Patrick Ohly 940f1ba7d8 sync output: hide "<source>: started" INFO messages
These messages get printed at the start of processing each
SyncML message. This is not particularly useful and just
adds noise to the output.
2014-04-01 16:45:09 +02:00
Patrick Ohly f33db08c43 syncing: remember original path to session dir
Nightly testing uses a "Client_Sync_Current" symlink to point
the server to a location where it shall write its per-test logs
without having to reconfigure the server.

When the server-side session runs longer than a specific test, it ends up
using the "Client_Sync_Current" link of the next test. "permission denied"
errors were also seen, although it is less certain whether that had the same
root cause.

To avoid such issues, the sync session now tries to resolve the log dir
path to an absolute path at the start of the session.
2014-03-31 11:11:56 +02:00
Patrick Ohly c1e894b5e7 message resend: be more conservative
When timing out, SyncContext nevertheless sometimes resent a message despite
being close to the final timeout deadline. Relax the math further so that more
time must remain before the deadline when attempting a resend.

The earlier behavior randomly broke some of the resend tests.
2014-01-17 16:15:16 +01:00
Patrick Ohly e407d71410 cppcheck performance: function parameter should be passed by reference
cppcheck found some minor cases where complex parameters were accidentally
passed by value.
2014-01-17 16:15:15 +01:00
Patrick Ohly e7a8f1b456 logging: support DLT (FDO #66769)
Diagnostic Log and Trace (DLT) manages a sequence of log messages,
with remote controllable level of detail. SyncEvolution optionally
(can be chosen at compile time and again at runtime) uses DLT instead
of its own syncevolution-log.html files.
2013-10-25 21:07:27 +01:00
Patrick Ohly ec9de82a7d SyncContext: use AuthProvider
When running a local sync, the syncURL/username/password are not meant
for the sync and cannot be used if they refer to an AuthProvider which
cannot return plain username/password.

In all other cases, this may or may not work, so at least try it instead
of hard-coding the IdentityProviderCredentials.
2013-10-01 09:28:38 +02:00
Patrick Ohly 83c515b950 SyncContext: use SimpleUserInterface without keyring access
Code-refactoring, the default user interface has the same functionality
as our dummy one if told to not use keyrings.
2013-10-01 09:28:38 +02:00
Patrick Ohly 526723acf5 config: first step towards modular identity providers
Let the conversion to username+password be handled by the
IdentityProvider module.
2013-09-27 08:59:14 -07:00
Patrick Ohly 7a28f3664c 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-09-27 08:59:14 -07:00
Patrick Ohly 401de08d5e SyncContext: avoid caching config tree for entire duration of client-test
Instantiating LogDirTest used to create a SyncContext and use that as logger
for the entire duration of testing inside client-test, even when not running
LogDirTest tests at all. This is undesirable and together with caching of the
config tree while in use, broke some other tests (EvolutionCalendarTest)
because obsolete DB names were shared.

It is better to create the context during setUp() and remove it in tearDown().
2013-09-27 08:59:13 -07:00
Patrick Ohly 37b03d5e8d 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-09-27 08:59:13 -07:00
Patrick Ohly 4c52378ec3 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-09-27 08:59:13 -07: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 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 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 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 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 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 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 6c551167c4 engine: change tracking optional for caching mode and item modification
Recording the revision of items during a caching sync is unnecessary
because the next sync will not use the information. For item
modifications, the information was not even recorded.

Now a "don't need changes" mode can be set in SyncSource, which is
done for caching and command line item operations. This is better than
second-guessing the mode in which a source is used.

SyncSourceRevision checks that flag and skips updating the
luid->revision mapping if set.

Individual backends can also check the flag and skip calculating the
revision to begin with.
2013-07-05 17:44:10 +02:00
Patrick Ohly ebef300ae5 SyncSource: support asynchronous add/update in utility classes
SyncSourceSerialize uses ITEM_AGAIN plus a callback in
InsertItemResult to indicate that and how an insert (aka add or
update) operation must be continued.

TrackingSyncSource merely passes that result through until it finally
completes.

Direct, raw access to items as done by the command line and restore
operations is not done asynchronously. The backend does not need to
know how it is used, the SyncSourceSerialize wrapper around the
backend will flush and wait.

Asynchronous deleting is not supported. It would require throwing an
exception or an API change (better - exceptions are for errors!)
because removeItem() has no return code which could be extended.
2013-07-05 17:44:09 +02:00
Patrick Ohly 856295b1e1 SyncSource: optional support for asynchronous insert/update/delete
The wrapper around the actual operation checks if the operation
returned an error or result code (traditional behavior). If not, it
expects a ContinueOperation instance, remembers it and calls it when
the same operation gets called again for the same item.

For add/insert, "same item" is detected based on the KeyH address,
which must not change. For delete, the item local ID is used.

Pre- and post-signals are called exactly once, before the first call
and after the last call of the item.

ContinueOperation is a simple boost::function pointer for now. The
Synthesis engine itself is not able to force completion of the
operation, it just polls. This can lead to many empty messages with
just an Alert inside, thus triggering the "endless loop" protection,
which aborts the sync.

We overcome this limitation in the SyncEvolution layer above the
Synthesis engine: first, we flush pending operations before starting
network IO. This is a good place to batch together all pending
operations. Second, to overcome the "endless loop" problem, we force
a waiting for completion if the last message already was empty. If
that happened, we are done with items and should start sending our
responses.

Binding a function which returns the traditional TSyError still works
because it gets copied transparently into the boost::variant that the
wrapper expects, so no other code in SyncSource or backends needs to
be adapted. Enabling the use of LOCERR_AGAIN in the utility classes
and backends will follow in the next patches.
2013-07-05 17:44:09 +02:00
Patrick Ohly 445d534388 SyncContext: "server" -> "peer" in debug message
The error message also applies to SyncML clients, so use "peer"
instead of "server".
2013-07-05 17:44:08 +02:00
Patrick Ohly 121b0e9066 SyncContext: include process name in Synthesis log
The process name has become essential to distinguish messages
from local sync parent and child, because the parent will include
the child's output in its own log.

We cannot pass a process name to the Synthesis logging mechanism, so
use the logging prefix instead. Relies on a patch to libsynthesis to
enable the logging of that prefix.
2013-07-05 17:44:08 +02:00
Patrick Ohly b4d880bb8a engine: fix "override blocking threading code in libsynthesis"
CondTimedWaitGLib() would not have returned immediately for
milliSecondsToWait == 0, as expected by the Synthesis engine.
Not sure whether it mattered in practice, though.
2013-06-20 12:19:44 +02:00
Patrick Ohly 8dd516846a engine: free engine while still protected from signals
Explicitly free the engine before releasing our lock on shutdown
signals. This prevents getting killed by a signal while we are still
freeing resources, which can take some time when a background thread
is involved (seen in some tests covering that).
2013-05-16 11:25:05 +02:00
Patrick Ohly 69b8780bde engine: avoid false resending of messages shortly before final timeout
The D-Bus TestHTTP tests occasionally failed because a message was resend
due to rounding issues. Be a bit (= 0.1 seconds) more conservative about
resending to avoid this.
2013-05-16 11:25:05 +02:00
Patrick Ohly b6b75de59b PIM: new return value for SyncPeer(), new SyncProgress signal (FDO #63417)
The SyncPeer() result is derived from the sync statistics. To have
them available, the "sync done" signal must include the SyncReport.

Start and end of a sync could already be detected; "modified" signals
while a sync runs depends on a new signal inside the SyncContext when
switching from one cycle to the next and at the end of the last one.
2013-05-16 11:24:48 +02:00
Patrick Ohly 9a3b17b82a engine: eliminate virtual checkForSuspend/Abort()
Since the introduction of SuspendFlags, the ony remaining user
of the virtual aspect of checkForSuspend/checkForAbort() was the
testing code. By using the suspend/abort request mechanism in
SuspendFlags, it becomes possible to move checkForSuspend/Abort()
into SuspendFlags itself.

This will be useful to use it outside of a SyncContext member.
2013-05-13 17:49:50 +02:00
Patrick Ohly 9d2df20ccc engine: override blocking threading code in libsynthesis
We need to keep the glib event loop running while the main thread
waits for the background thread to finish. Otherwise code using
glib events (like EDS) may get stuck (observed with Sleep()
when using g_timeout_add() and synchronous calls in EDS 3.6).

We also need to watch for abort requests. When aborted, we give up
waiting for the thread and tell the engine to proceed. This will
eventually return control to us, where we can shut down.

When libsynthesis shuts down, it'll wait forever for the background
thread's shutdown. In this case we must wait and hope that the background
thread completes or aborts by itself.
2013-05-13 17:49:50 +02:00
Patrick Ohly 9a4c770d8e engine: prevent timeouts in HTTP server mode
HTTP SyncML clients give up after a certain timeout (SyncEvolution
after RetryDuration = 5 minutes by default, Nokia e51 after 15
minutes) when the server fails to respond.

This can happen with SyncEvolution as server when it uses a slow
storage with many items, for example via WebDAV. In the case of slow
session startup, multithreading is now used to run the storage
initializing in parallel to sending regular "keep-alive" SyncML
replies to the client.

By default, these replies are sent every 2 minutes. This can be
configured with another extensions of the SyncMLVersion property:
  SyncMLVersion = REQUESTMAXTIME=5m

Other modes do not use multithreading by default, but it can be
enabled by setting REQUESTMAXTIME explicitly. It can be disabled
by setting the time to zero.

The new feature depends on a libsynthesis with multithreading enabled
and glib >= 2.32.0, which is necessary to make SyncEvolution itself
thread-safe. With an older glib, multithreading is disabled, but can
be enabled as a stop-gap measure by setting REQUESTMAXTIME explicitly.
2013-05-13 17:49:50 +02:00
Patrick Ohly 2032d17098 engine: event processing when using multithreading
Only one thread may handle events in the default context at any point
in time. If a second thread calls g_main_context_iteration() or
g_main_loop_run(), it blocks until the other thread releases ownership
of the context. In that case, the first thread may wake up because of
an event that the second thread waits for, in which case the second
thread may never wake up. See
https://mail.gnome.org/archives/gtk-list/2013-April/msg00040.html

This means that SyncEvolution can no longer rely on these functions
outside of the main thread. This affects Sleep() and the EDS backend.

As an interim solution, take over permanent ownership of the default
context in the main thread. This prevents fights over the ownership
when the main thread enters and leaves the main loop
repeatedly. Utility code using the main context must check for
ownership first and fall back to some other means when not the owner.

The assumption for the fallback is that the main thread will drive the
event loop, so polling with small delays for the expected status
change (like "view complete" in the EDS backend) is going to succeed
eventually.

A better solution would be to have one thread running the event loop
permanently and push all event handling into that thread. There is C++
utility code for such things in:
http://cxx-gtk-utils.sourceforge.net/2.0/index.html

See in particular the TaskManager class and its
make_task_when()/make_task_compose()/make_task_when_full() functions
for executing asynchronous results via a glib main loop, also the
Future::when() method and a number of other similar things in the
library.
2013-05-13 17:49:50 +02:00
Patrick Ohly e154b747d2 engine: better transport timeout handling
Use the monotonic system time. Timespec has sub-second resolution and
by using the monotonic time, we are independent of time corrections.

If retryDuration is smaller than retryInterval, then time out after
retryDuration instead of waiting once for retryInterval and then
checking retryDuration.

When the request timed out *exactly* after retryDuration or the next
resend would happen after the retryDuration, then give up immediately.
2013-05-13 17:49:49 +02:00
Patrick Ohly 649837c2c2 Logging: thread-safe
Logging must be thread-safe, because the glib log callback may be
called from arbitrary threads. This becomes more important with EDS
3.8, because it shifts the execution of synchronous calls into
threads.

Thread-safe logging will also be required for running the Synthesis
engine multithreaded, to overlap SyncML client communication with
preparing the sources.

To achieve this, the core Logging module protects its global data with
a recursive mutex. A recursive mutes is used because logging calls
themselves may be recursive, so ensuring single-lock semantic would be
hard.

Ref-counted boost pointers are used to track usage of Logger
instances.  This allows removal of an instance from the logging stack
while it may still be in use. Destruction then will be delayed until
the last user of the instance drops it. The instance itself must be
prepared to handle this.

The Logging mutex is available to users of the Logging module. Code
which holds the logging mutex should not lock any other mutex, to
avoid deadlocks. The new code is a bit fuzzy on that, because it calls
other modules (glib, Synthesis engine) while holding the mutex. If
that becomes a problem, then the mutex can be unlocked, at the risk of
leading to reordered log messages in different channels (see
ServerLogger).

Making all loggers follow the new rules uses different
approaches.

Loggers like the one in the local transport child which use a parent
logger and an additional ref-counted class like the D-Bus helper keep
a weak reference to the helper and lock it before use. If it is gone
already, the second logging part is skipped. This is the recommended
approach.

In cases where introducing ref-counting for the second class would
have been too intrusive (Server and SessionHelper), a fake
boost::shared_ptr without a destructor is used as an intermediate step
towards the recommended approach. To avoid race conditions while the
instance these fake pointers refer to destructs, an explicit
"remove()" method is necessary which must hold the Logging
mutex. Using the potentially removed pointer must do the same. Such
fake ref-counted Loggers cannot be used as parent logger of other
loggers, because then remove() would not be able to drop the last
reference to the fake boost::shared_ptr.

Loggers with fake boost::shared_ptr must keep a strong reference,
because no-one else does. The goal is to turn this into weak
references eventually.

LogDir must protect concurrent access to m_report and the Synthesis
engine.

The LogRedirectLogger assumes that it is still the active logger while
disabling itself. The remove() callback method will always be invoked
before removing a logger from the stack.
2013-05-06 16:28:13 +02:00
Patrick Ohly 2f6f880910 Logging: merge Logger and LoggerBase
Having two separate classes had little (no?!) benefit and just
caused confusion.
2013-05-06 16:28:13 +02:00
Patrick Ohly ff2c4584b2 Logging: remove obsolete isProcessSafe()
The method became obsolete when introducing fork+exec for local
syncing. Before that, the method was used to remove unsafe loggers in
the child's process. Now exec() does that for us.
2013-05-06 16:28:13 +02:00
Patrick Ohly 30955bab34 Logging: move messagev parameters into struct, rename different versions of messagev
The number of parameters for messagev has grown unreasonably, and more
parameters will be needed soon (explicit process name). Better store
the parameters in a struct and pass around a pointer to such a struct
instance. The code becomes shorter and new parameters can be passed
through intermediate functions without modifying them.
2013-05-06 16:28:13 +02:00
Patrick Ohly 4f8615ee8b Logging: eliminate _instance from SE_LOG* macros
With the _instance parameter always being NULL thanks to the previous
patch, it can be removed completely.
2013-05-06 16:28:13 +02:00
Patrick Ohly b5befe6cbf Logging: remove usage of Logger instance
Passing an explicit Logger instance to the SE_LOG* macros was hardly
ever used and only made the macros more complex.

The only usage of it was in some backends, which then added a prefix
string automatically. The same effect can be achieved by passing
getDisplayName(). Exception handling no longer needs a Logger instance,
the prefix alone is enough.

The other intended usage, avoiding global variables for logging by
passing a logger known to the caller, was not possible at all.

To make prefix handling more flexible, it is now passed as a "const
std::string *" instead of a "const char *".
2013-05-06 16:28:12 +02:00
Patrick Ohly 132e915624 engine: call getenv() only once
Helps Klocwork, which otherwise warned about the potential
NULL return from the second call.
2013-05-06 16:28:11 +02:00