Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed a race condition while adding and cancelling an observation #169

Conversation

balsmn
Copy link
Contributor

@balsmn balsmn commented Aug 24, 2016

This PR fixes a race condition in CaliforniumObservationRegistryImpl while invoking addObservation and cancelObservation calls. Due to this race condition it could still be possible to have a duplicate observation for the same resource and client reported in #163

Due to change that came in as a bug fix for issue #168 there can be at most only one active observation for a given resource. So the ObservationRegistry interface was changed to reflect the same.

Signed-off-by: Bala Azhagappan balasubramanian.azhagappan@bosch-si.com

@@ -64,6 +66,7 @@

private final List<ObservationRegistryListener> listeners = new CopyOnWriteArrayList<>();
private final Map<KeyToken, Observation> observationsByToken = new ConcurrentHashMap<>();
private final Lock observationLock = new ReentrantLock();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why us a Lock and not a synchronize(this) ?

Copy link
Contributor Author

@balsmn balsmn Aug 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notifying Observation listeners is outside the locks. At the end the same can also be achieved using synchronized blocks. Its just a religious thing which one you chose.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to use a lock that is private to the class. Otherwise someone else could also synchronize on "this" and we might get a deadlock (more a theoretical and style discussion).

Of course we can also synchronize on a private object and use synchronized blocks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no good reason to use a lock here, you can use a private monitor. "private Object monitor = new Object();" if you really want to isolate it.

A synchronize on monitor is superior here because you don't have to rely on the try/finally and you are not using the extra feature of Lock missing from synchronize block.

That's no religious/style thing, just better idiomatic java 😄

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I meant with the last sentence. We can use a private monitor.

@balsmn balsmn force-pushed the fix_race_condition_while_adding_observation branch 2 times, most recently from 47fff24 to 7f695ff Compare August 25, 2016 13:51
…tially lead to duplicate observes on the same resource of the same client.

Signed-off-by: Bala Azhagappan <balasubramanian.azhagappan@bosch-si.com>
@balsmn
Copy link
Contributor Author

balsmn commented Aug 25, 2016

@jvermillard as you suggested, I have pushed the updated version with the two changes.

@sbernard31
Copy link
Contributor

sbernard31 commented Aug 25, 2016

Manu is modifying this code and your PR will not be so relevant in the new code.

But finally this constraint of duplicate observation should not be handled at Leshan level. This is a CoAP constraint so this should be done in californium.

@balsmn
Copy link
Contributor Author

balsmn commented Aug 26, 2016

I agree with you regarding only one observation per resource restriction belonging to californium. The fact that we have an ObservationStore in Californium layer and an ObservationRegistry in Leshan leads to replicate the californium restriction to Leshan layer.

Could you give a heads up what kind of changes are to be expected in the new code? Is it only reimplementing ObservationRegistry or we would not have an ObservationRegistry?

@sbernard31
Copy link
Contributor

The Observe CoAP spec §3.1 say:
"A client MUST aggregate such requests and MUST NOT register more than once for the same target resource. The target resource is identified by all options in the request that are part of the Cache-Key. This includes, for example, the full request URI and the Accept Option."

Currently in californium, there is no limitation about that. An obversation is just identifying by a Token.

The spec say that a target resource is identified by all the options §5.10 that are part of the cache key (= all options except size1). But, as we deviate a little from the spec by allowing observation from different endpoint (This is the case where the CoAP server is behind a NAT), Using the Cache-Key is not so relevant...

So I'm not so sure pushing this restriction in californium is still a good idea...

Could you give a heads up what kind of changes are to be expected in the new code? Is it only reimplementing ObservationRegistry or we would not have an ObservationRegistry?

Manu will probably push a PR before the end of the week.

@sbernard31
Copy link
Contributor

So Manu pushed its code in the observe_context branch which needs this additionnal feature in Californium.

Unfortunately, this will not fix the race condition you find here.
A possible solution could be to let the ObservationStore removing old observation(s?) as it is in charge to keep the store in a consistent state. Ideally, it should notify Californium that the request is cancelled.

There is another race condition between observe and registration, but we think we found a miss-conception in Leshan. As observation is strongly linked to the registration, we think that observation should be store in ClientRegistry(RegistrationStore)

What do you think ?

@balsmn
Copy link
Contributor Author

balsmn commented Sep 8, 2016

Yes I agree that Observation is strongly linked to a registration.

we think that observation should be store in ClientRegistry(RegistrationStore)

You mean to say that instead of having a separate ObservationRegistry, just have the RegistrationStore implement the CaliforniumObservationRegistry or even the new LwM2mObservationStore interface introduced in the branch (observe_context) and clear the observations when a de-registration happens?

@balsmn
Copy link
Contributor Author

balsmn commented Sep 8, 2016

Unfortunately, this will not fix the race condition you find here.
A possible solution could be to let the ObservationStore removing old observation(s?) as it is in charge to keep the store in a consistent state. Ideally, it should notify Californium that the request is cancelled.

I agree. If InMemoryObservationStore while adding, can also cancel any existing observations. That means, the add(Observation) of ObservationStore should return list of observations removed/canceled while adding. I see that you have already done this in your Californium-PR#87

When it is implemented that way and merged in to master, then this PR will not be relevant any more, if not it would still be good to have this PR.

I have a small request. As the refactoring done in CaliforniumObservationRegistry as part of the observe-request-context has nothing to do with the observe request's extention with a context info, it would be good to separate this refactoring from the actual observe request context implementations when creating PR's. What do you think ?

@sbernard31
Copy link
Contributor

You mean to say that instead of having a separate ObservationRegistry, just have the RegistrationStore implement the CaliforniumObservationRegistry or even the new LwM2mObservationStore interface introduced in the branch (observe_context) and clear the observations when a de-registration happens?

Something like this but I need to think more about this.

@msangoi
Copy link
Contributor

msangoi commented Sep 15, 2016

I have a small request. As the refactoring done in CaliforniumObservationRegistry as part of the observe-request-context has nothing to do with the observe request's extention with a context info, it would be good to separate this refactoring from the actual observe request context implementations when creating PR's. What do you think ?

I'm not sure to understand why it is needed to separate this. I agree that the registry refactoring could have been done in a separate PR, but then the code handling the observe context would have been duplicated.

@sbernard31
Copy link
Contributor

Manu changes was integrated in master so the PR si no more relevant.
I open the issue to track that this race condition is still present. #176

@sbernard31 sbernard31 closed this Sep 20, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants