AW: Semaphors with timeouts

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

AW: Semaphors with timeouts

Mülheims, Klaus
Hi,

After testing the different approaches I decided to use TimedPromises for my problem.
But I overrided the method value, because it uses recursions, if the signalTimeout-exception was resumed. This is an ugly design, because you cannot know the recursion depth. In my program, every 10 seconds such an exception is thrown and resumed. Sometimes, it lasts for days until the value is computated, so you can imagine, how many recursions are stored on the stack.
I redesigned the method as follows:

TimedPromise>>value
        [| hasResult |
        delay wait. "Wait for data arrival or alarm expiry."
        hasResult := delay inProgress.
        delay disable.
        sync signal. "To allow multiple reads of the result"
        exception == nil
                ifTrue:
                        [hasResult
                                ifTrue: [^value]
                                ifFalse:
                                        [self signalTimeout.
                                        "If resumed, start over"
                                        sync wait "Undo the signal above"]]
                ifFalse:
                        [^exception
                                clearForReraise;
                                searchFrom: thisContext;
                                raise]]
                        repeat

Maybe someone from Cincom uses this change for the next release :-).

Greeting

Klaus Mülheims

Collogia AG
Ubierring 11
 
50678 Köln
Germany
+49 221 336080
http://www.collogia.de

-----Ursprüngliche Nachricht-----
Von: Mülheims, Klaus [mailto:[hidden email]]
Gesendet: Montag, 4. September 2006 17:16
An: vwnc-list
Betreff: Semaphors with timeouts

Hi,

I need a kind of Semaphore that waits only a predefined timeout, something like:
sem := Semaphore new.
gotSem := sem waitMaxTime: 45.

This methods returns true if a could enter the critical section. But if I'm blocked, I am only willing to wait for 45 seconds. If I cannot enter the critical section in this time, the method returns false and i can react on this timeout.

Has anybody seen such a behaviour in VisualWorks?

Greetings

Klasu Muelheims


Collogia AG
Ubierring 11
 
50678 Köln
Germany
+49 221 336080
http://www.collogia.de


Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt.


Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt.
Reply | Threaded
Open this post in threaded view
|

TimedPromise can't be debugged easily - WAS: Semaphors with timeouts

Joerg Beekmann, DeepCove Labs (YVR)
Klaus

TimedPromise solves some problems elegantly. However there is a major annoyance with them- When something goes wrong it is not possible to debug the code inside the promise block. To see this evaluate the following:

promise := [Transcript show: 'start';cr.
'asdasd' /3.
Transcript show: 'bar'] timedPromiseFor: 10000.
promise value.

The debugger is positioned at the value send and it is not possible to get into the block. In the example above you can at least see the source but if the block is created in another method then you don't even get that. This is broken up to and including 7.4.1.

Now if 'asdasd' /3. is replaced with self halt. The debugger does work work correctly so I imagine it should be possible to fix this.

Joerg


> -----Original Message-----
> From: Mülheims, Klaus [mailto:[hidden email]]
> Sent: September 12, 2006 1:53 AM
> To: vwnc-list
> Subject: AW: Semaphors with timeouts
>
> Hi,
>
> After testing the different approaches I decided to use TimedPromises for
> my problem.
> But I overrided the method value, because it uses recursions, if the
> signalTimeout-exception was resumed. This is an ugly design, because you
> cannot know the recursion depth. In my program, every 10 seconds such an
> exception is thrown and resumed. Sometimes, it lasts for days until the
> value is computated, so you can imagine, how many recursions are stored on
> the stack.
> I redesigned the method as follows:
>
> TimedPromise>>value
> [| hasResult |
> delay wait. "Wait for data arrival or alarm expiry."
> hasResult := delay inProgress.
> delay disable.
> sync signal. "To allow multiple reads of the result"
> exception == nil
> ifTrue:
> [hasResult
> ifTrue: [^value]
> ifFalse:
> [self signalTimeout.
> "If resumed, start over"
> sync wait "Undo the signal above"]]
> ifFalse:
> [^exception
> clearForReraise;
> searchFrom: thisContext;
> raise]]
> repeat
>
> Maybe someone from Cincom uses this change for the next release :-).
>
> Greeting
>
> Klaus Mülheims
>
> Collogia AG
> Ubierring 11
>
> 50678 Köln
> Germany
> +49 221 336080
> http://www.collogia.de
>
> -----Ursprüngliche Nachricht-----
> Von: Mülheims, Klaus [mailto:[hidden email]]
> Gesendet: Montag, 4. September 2006 17:16
> An: vwnc-list
> Betreff: Semaphors with timeouts
>
> Hi,
>
> I need a kind of Semaphore that waits only a predefined timeout, something
> like:
> sem := Semaphore new.
> gotSem := sem waitMaxTime: 45.
>
> This methods returns true if a could enter the critical section. But if
> I'm blocked, I am only willing to wait for 45 seconds. If I cannot enter
> the critical section in this time, the method returns false and i can
> react on this timeout.
>
> Has anybody seen such a behaviour in VisualWorks?
>
> Greetings
>
> Klasu Muelheims
>
>
> Collogia AG
> Ubierring 11
>
> 50678 Köln
> Germany
> +49 221 336080
> http://www.collogia.de
>
>
> Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte
> Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren
> oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-
> Mails übernehmen wir keine Haftung für den Inhalt.
>
>
> Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte
> Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren
> oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-
> Mails übernehmen wir keine Haftung für den Inhalt.

Reply | Threaded
Open this post in threaded view
|

Re: TimedPromise can't be debugged easily - WAS: Semaphors with timeouts

kobetic
Joerg Beekmann wrote:

> TimedPromise solves some problems elegantly. However there is a major
> annoyance with them- When something goes wrong it is not possible to
> debug the code inside the promise block. To see this evaluate the
> following:
>
> promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript
> show: 'bar'] timedPromiseFor: 10000. promise value.
>
> The debugger is positioned at the value send and it is not possible
> to get into the block. In the example above you can at least see the
> source but if the block is created in another method then you don't
> even get that. This is broken up to and including 7.4.1.
>
> Now if 'asdasd' /3. is replaced with self halt. The debugger does
> work work correctly so I imagine it should be possible to fix this.

What would you expect the fixed behavior to be? The only thing I can
imagine is modifying the debugger so that when you step into
timedPromiseFor:, it would open another debugger for the process that
runs the block. That way you could step through both processes any way
you want. The same argument could probably be made for any code that
forks or creates a new process. However I'm not sure how practical that
would end up being. It may well be that putting a breakpoint at the
exact place you want a debugger to open would often be a more efficient
approach anyway. I find that when debugging a problem involving multiple
processes decent logging is the best tool to pin point the place to look
at and then put a breakpoint there.

Martin

Reply | Threaded
Open this post in threaded view
|

RE: TimedPromise can't be debugged easily

Joerg Beekmann, DeepCove Labs (YVR)
Hello Martin

I am not expecting to be able to step into a timed promise, I just want
to be able to debug an exception that arrises within the promise block.
You comparison to just a normally forked block is helpful. In a
workspace do the following to initialize the variable aBlock:

aBlock := [Transcript show: 'start';cr.
'asdasd' /3.
Transcript show: 'bar'].

Then try the following:

aBlock fork.

As you would expect how you can debug the exception that is raised
within the block.

Now try the following:

(aBlock timedPromiseFor: 10000) value

In this case there is no information about the excepion or its context.

Joerg


> -----Original Message-----
> From: Martin Kobetic [mailto:[hidden email]]
> Sent: September 18, 2006 9:33 AM
> To: Joerg Beekmann
> Cc: vwnc-list
> Subject: Re: TimedPromise can't be debugged easily - WAS:
> Semaphors with timeouts
>
> Joerg Beekmann wrote:
> > TimedPromise solves some problems elegantly. However there
> is a major
> > annoyance with them- When something goes wrong it is not
> possible to
> > debug the code inside the promise block. To see this evaluate the
> > following:
> >
> > promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript
> > show: 'bar'] timedPromiseFor: 10000. promise value.
> >
> > The debugger is positioned at the value send and it is not
> possible to
> > get into the block. In the example above you can at least see the
> > source but if the block is created in another method then you don't
> > even get that. This is broken up to and including 7.4.1.
> >
> > Now if 'asdasd' /3. is replaced with self halt. The
> debugger does work
> > work correctly so I imagine it should be possible to fix this.
>
> What would you expect the fixed behavior to be? The only
> thing I can imagine is modifying the debugger so that when
> you step into timedPromiseFor:, it would open another
> debugger for the process that runs the block. That way you
> could step through both processes any way you want. The same
> argument could probably be made for any code that forks or
> creates a new process. However I'm not sure how practical
> that would end up being. It may well be that putting a
> breakpoint at the exact place you want a debugger to open
> would often be a more efficient approach anyway. I find that
> when debugging a problem involving multiple processes decent
> logging is the best tool to pin point the place to look at
> and then put a breakpoint there.
>
> Martin
>

Reply | Threaded
Open this post in threaded view
|

Re: TimedPromise can't be debugged easily

kobetic
Hi Joerg,

OK, I see. It seems that we have conflicting requirements then.
Basically you don't want Errors in the promise block to be handled (See
BlockClosure>>promiseBlock:). However while that might be handy for
debugging, it makes things more difficult for runtime. Currently any
errors will be captured and injected into the calling process through
the promise. They will be resignaled there, so the caller can use normal
exception handling to react to the problems. Otherwise you'll just have
notifiers popping up from the background thread with no chance to
intervene. It's true that the resignaled exception won't have the
original context where it was created, since that process is long gone
by then, but you have all the other information there.

I'm not sure how to resolve this. You can have a subclass of Promise
that would behave one way or the other based on some global switch, but
it may become unmanageable with heavy use of promises. An instance based
flag is usually a pain to work with though. I'm afraid you'll have to
pick your poison here.

Martin

Joerg Beekmann wrote:

> Hello Martin
>
> I am not expecting to be able to step into a timed promise, I just want
> to be able to debug an exception that arrises within the promise block.
> You comparison to just a normally forked block is helpful. In a
> workspace do the following to initialize the variable aBlock:
>
> aBlock := [Transcript show: 'start';cr.
> 'asdasd' /3.
> Transcript show: 'bar'].
>
> Then try the following:
>
> aBlock fork.
>
> As you would expect how you can debug the exception that is raised
> within the block.
>
> Now try the following:
>
> (aBlock timedPromiseFor: 10000) value
>
> In this case there is no information about the excepion or its context.
>
> Joerg
>
>
>
>>-----Original Message-----
>>From: Martin Kobetic [mailto:[hidden email]]
>>Sent: September 18, 2006 9:33 AM
>>To: Joerg Beekmann
>>Cc: vwnc-list
>>Subject: Re: TimedPromise can't be debugged easily - WAS:
>>Semaphors with timeouts
>>
>>Joerg Beekmann wrote:
>>
>>>TimedPromise solves some problems elegantly. However there
>>
>>is a major
>>
>>>annoyance with them- When something goes wrong it is not
>>
>>possible to
>>
>>>debug the code inside the promise block. To see this evaluate the
>>>following:
>>>
>>>promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript
>>>show: 'bar'] timedPromiseFor: 10000. promise value.
>>>
>>>The debugger is positioned at the value send and it is not
>>
>>possible to
>>
>>>get into the block. In the example above you can at least see the
>>>source but if the block is created in another method then you don't
>>>even get that. This is broken up to and including 7.4.1.
>>>
>>>Now if 'asdasd' /3. is replaced with self halt. The
>>
>>debugger does work
>>
>>>work correctly so I imagine it should be possible to fix this.
>>
>>What would you expect the fixed behavior to be? The only
>>thing I can imagine is modifying the debugger so that when
>>you step into timedPromiseFor:, it would open another
>>debugger for the process that runs the block. That way you
>>could step through both processes any way you want. The same
>>argument could probably be made for any code that forks or
>>creates a new process. However I'm not sure how practical
>>that would end up being. It may well be that putting a
>>breakpoint at the exact place you want a debugger to open
>>would often be a more efficient approach anyway. I find that
>>when debugging a problem involving multiple processes decent
>>logging is the best tool to pin point the place to look at
>>and then put a breakpoint there.
>>
>>Martin
>>
>
>

Reply | Threaded
Open this post in threaded view
|

RE: TimedPromise can't be debugged easily

Joerg Beekmann, DeepCove Labs (YVR)
Hi Martin

Humm I see the issue. At first I thought the promise process could just
block and one could then user the ProcessManager to debug it, but in
that case the promise will not return so that's no good.

> is long gone by then, but you have all the other information there.

Well, more information would definitly help. What about capturing a
stack trace or even a portion of one.


Joerg

> -----Original Message-----
> From: Martin Kobetic [mailto:[hidden email]]
> Hi Joerg,
>
> OK, I see. It seems that we have conflicting requirements then.
> Basically you don't want Errors in the promise block to be
> handled (See
> BlockClosure>>promiseBlock:). However while that might be handy for
> debugging, it makes things more difficult for runtime.
> Currently any errors will be captured and injected into the
> calling process through the promise. They will be resignaled
> there, so the caller can use normal exception handling to
> react to the problems. Otherwise you'll just have notifiers
> popping up from the background thread with no chance to
> intervene. It's true that the resignaled exception won't have
> the original context where it was created, since that process
> is long gone by then, but you have all the other information there.
>
> I'm not sure how to resolve this. You can have a subclass of
> Promise that would behave one way or the other based on some
> global switch, but it may become unmanageable with heavy use
> of promises. An instance based flag is usually a pain to work
> with though. I'm afraid you'll have to pick your poison here.
>
> Martin
>
> Joerg Beekmann wrote:
>
> > Hello Martin
> >
> > I am not expecting to be able to step into a timed promise, I just
> > want to be able to debug an exception that arrises within
> the promise block.
> > You comparison to just a normally forked block is helpful. In a
> > workspace do the following to initialize the variable aBlock:
> >
> > aBlock := [Transcript show: 'start';cr.
> > 'asdasd' /3.
> > Transcript show: 'bar'].
> >
> > Then try the following:
> >
> > aBlock fork.
> >
> > As you would expect how you can debug the exception that is raised
> > within the block.
> >
> > Now try the following:
> >
> > (aBlock timedPromiseFor: 10000) value
> >
> > In this case there is no information about the excepion or
> its context.
> >
> > Joerg
> >
> >
> >
> >>-----Original Message-----
> >>From: Martin Kobetic [mailto:[hidden email]]
> >>Sent: September 18, 2006 9:33 AM
> >>To: Joerg Beekmann
> >>Cc: vwnc-list
> >>Subject: Re: TimedPromise can't be debugged easily - WAS:
> >>Semaphors with timeouts
> >>
> >>Joerg Beekmann wrote:
> >>
> >>>TimedPromise solves some problems elegantly. However there
> >>
> >>is a major
> >>
> >>>annoyance with them- When something goes wrong it is not
> >>
> >>possible to
> >>
> >>>debug the code inside the promise block. To see this evaluate the
> >>>following:
> >>>
> >>>promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript
> >>>show: 'bar'] timedPromiseFor: 10000. promise value.
> >>>
> >>>The debugger is positioned at the value send and it is not
> >>
> >>possible to
> >>
> >>>get into the block. In the example above you can at least see the
> >>>source but if the block is created in another method then
> you don't
> >>>even get that. This is broken up to and including 7.4.1.
> >>>
> >>>Now if 'asdasd' /3. is replaced with self halt. The
> >>
> >>debugger does work
> >>
> >>>work correctly so I imagine it should be possible to fix this.
> >>
> >>What would you expect the fixed behavior to be? The only
> thing I can
> >>imagine is modifying the debugger so that when you step into
> >>timedPromiseFor:, it would open another debugger for the
> process that
> >>runs the block. That way you could step through both
> processes any way
> >>you want. The same argument could probably be made for any
> code that
> >>forks or creates a new process. However I'm not sure how practical
> >>that would end up being. It may well be that putting a
> breakpoint at
> >>the exact place you want a debugger to open would often be a more
> >>efficient approach anyway. I find that when debugging a problem
> >>involving multiple processes decent logging is the best tool to pin
> >>point the place to look at and then put a breakpoint there.
> >>
> >>Martin
> >>
> >
> >
>
>

Reply | Threaded
Open this post in threaded view
|

RE: TimedPromise can't be debugged easily

Terry Raymond
Joerg

I don't get it, why not put a breakpoint in
BlockClosure>>promiseBlock:?

Terry
 
===========================================================
Terry Raymond       Smalltalk Professional Debug Package
Crafted Smalltalk
80 Lazywood Ln.
Tiverton, RI  02878
(401) 624-4517      [hidden email]
<http://www.craftedsmalltalk.com>
===========================================================

> -----Original Message-----
> From: Joerg Beekmann [mailto:[hidden email]]
> Sent: Tuesday, September 19, 2006 2:09 PM
> To: Martin Kobetic
> Cc: vwnc-list
> Subject: RE: TimedPromise can't be debugged easily
>
> Hi Martin
>
> Humm I see the issue. At first I thought the promise process could just
> block and one could then user the ProcessManager to debug it, but in
> that case the promise will not return so that's no good.
>
> > is long gone by then, but you have all the other information there.
>
> Well, more information would definitly help. What about capturing a
> stack trace or even a portion of one.
>
>
> Joerg
>
> > -----Original Message-----
> > From: Martin Kobetic [mailto:[hidden email]]
> > Hi Joerg,
> >
> > OK, I see. It seems that we have conflicting requirements then.
> > Basically you don't want Errors in the promise block to be
> > handled (See
> > BlockClosure>>promiseBlock:). However while that might be handy for
> > debugging, it makes things more difficult for runtime.
> > Currently any errors will be captured and injected into the
> > calling process through the promise. They will be resignaled
> > there, so the caller can use normal exception handling to
> > react to the problems. Otherwise you'll just have notifiers
> > popping up from the background thread with no chance to
> > intervene. It's true that the resignaled exception won't have
> > the original context where it was created, since that process
> > is long gone by then, but you have all the other information there.
> >
> > I'm not sure how to resolve this. You can have a subclass of
> > Promise that would behave one way or the other based on some
> > global switch, but it may become unmanageable with heavy use
> > of promises. An instance based flag is usually a pain to work
> > with though. I'm afraid you'll have to pick your poison here.
> >
> > Martin
> >
> > Joerg Beekmann wrote:
> >
> > > Hello Martin
> > >
> > > I am not expecting to be able to step into a timed promise, I just
> > > want to be able to debug an exception that arrises within
> > the promise block.
> > > You comparison to just a normally forked block is helpful. In a
> > > workspace do the following to initialize the variable aBlock:
> > >
> > > aBlock := [Transcript show: 'start';cr.
> > > 'asdasd' /3.
> > > Transcript show: 'bar'].
> > >
> > > Then try the following:
> > >
> > > aBlock fork.
> > >
> > > As you would expect how you can debug the exception that is raised
> > > within the block.
> > >
> > > Now try the following:
> > >
> > > (aBlock timedPromiseFor: 10000) value
> > >
> > > In this case there is no information about the excepion or
> > its context.
> > >
> > > Joerg
> > >
> > >
> > >
> > >>-----Original Message-----
> > >>From: Martin Kobetic [mailto:[hidden email]]
> > >>Sent: September 18, 2006 9:33 AM
> > >>To: Joerg Beekmann
> > >>Cc: vwnc-list
> > >>Subject: Re: TimedPromise can't be debugged easily - WAS:
> > >>Semaphors with timeouts
> > >>
> > >>Joerg Beekmann wrote:
> > >>
> > >>>TimedPromise solves some problems elegantly. However there
> > >>
> > >>is a major
> > >>
> > >>>annoyance with them- When something goes wrong it is not
> > >>
> > >>possible to
> > >>
> > >>>debug the code inside the promise block. To see this evaluate the
> > >>>following:
> > >>>
> > >>>promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript
> > >>>show: 'bar'] timedPromiseFor: 10000. promise value.
> > >>>
> > >>>The debugger is positioned at the value send and it is not
> > >>
> > >>possible to
> > >>
> > >>>get into the block. In the example above you can at least see the
> > >>>source but if the block is created in another method then
> > you don't
> > >>>even get that. This is broken up to and including 7.4.1.
> > >>>
> > >>>Now if 'asdasd' /3. is replaced with self halt. The
> > >>
> > >>debugger does work
> > >>
> > >>>work correctly so I imagine it should be possible to fix this.
> > >>
> > >>What would you expect the fixed behavior to be? The only
> > thing I can
> > >>imagine is modifying the debugger so that when you step into
> > >>timedPromiseFor:, it would open another debugger for the
> > process that
> > >>runs the block. That way you could step through both
> > processes any way
> > >>you want. The same argument could probably be made for any
> > code that
> > >>forks or creates a new process. However I'm not sure how practical
> > >>that would end up being. It may well be that putting a
> > breakpoint at
> > >>the exact place you want a debugger to open would often be a more
> > >>efficient approach anyway. I find that when debugging a problem
> > >>involving multiple processes decent logging is the best tool to pin
> > >>point the place to look at and then put a breakpoint there.
> > >>
> > >>Martin
> > >>
> > >
> > >
> >
> >

Reply | Threaded
Open this post in threaded view
|

Re: AW: Semaphors with timeouts

kobetic
In reply to this post by Mülheims, Klaus
Sorry about a late response, but I hope better late then never in this
case. I created AR#51276: "Resuming a PromiseExpiredError entails a
recursive call, can we avoid that ?" for your proposal and we will
consider it.

Thanks,

Martin

Mülheims wrote:

> Hi,
>
> After testing the different approaches I decided to use TimedPromises for my problem.
> But I overrided the method value, because it uses recursions, if the signalTimeout-exception was resumed. This is an ugly design, because you cannot know the recursion depth. In my program, every 10 seconds such an exception is thrown and resumed. Sometimes, it lasts for days until the value is computated, so you can imagine, how many recursions are stored on the stack.
> I redesigned the method as follows:
>
> TimedPromise>>value
> [| hasResult |
> delay wait. "Wait for data arrival or alarm expiry."
> hasResult := delay inProgress.
> delay disable.
> sync signal. "To allow multiple reads of the result"
> exception == nil
> ifTrue:
> [hasResult
> ifTrue: [^value]
> ifFalse:
> [self signalTimeout.
> "If resumed, start over"
> sync wait "Undo the signal above"]]
> ifFalse:
> [^exception
> clearForReraise;
> searchFrom: thisContext;
> raise]]
> repeat
>
> Maybe someone from Cincom uses this change for the next release :-).
>
> Greeting
>
> Klaus Mülheims
>
> Collogia AG
> Ubierring 11
>  
> 50678 Köln
> Germany
> +49 221 336080
> http://www.collogia.de
>
> -----Ursprüngliche Nachricht-----
> Von: Mülheims, Klaus [mailto:[hidden email]]
> Gesendet: Montag, 4. September 2006 17:16
> An: vwnc-list
> Betreff: Semaphors with timeouts
>
> Hi,
>
> I need a kind of Semaphore that waits only a predefined timeout, something like:
> sem := Semaphore new.
> gotSem := sem waitMaxTime: 45.
>
> This methods returns true if a could enter the critical section. But if I'm blocked, I am only willing to wait for 45 seconds. If I cannot enter the critical section in this time, the method returns false and i can react on this timeout.
>
> Has anybody seen such a behaviour in VisualWorks?
>
> Greetings
>
> Klasu Muelheims
>
>
> Collogia AG
> Ubierring 11
>  
> 50678 Köln
> Germany
> +49 221 336080
> http://www.collogia.de
>
>
> Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt.
>
>
> Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt.