In my implementation of Java NIO I have not been able to get SelectionKey.attach() to work. Basically, once clients connect (OP_ACCEPT interest ops) I add them to a map where their IP address maps to an object that maintains state for the client. Then, when an OP_READ occurs, I again retrieve the client's IP address, and this time get the value from the map and get the client's state object that way.
The problem here is that I have to do a map lookup EVERY TIME data is read from the network. There is a lot of wasted work going on there. So, I was thrilled to see that you can attach an arbitrary object type to a SelectionKey, which should be easily retrieved when you call SelectionKey.attachment(), even if we are now handling a different event (retrieved during OP_READ versus put into the map during OP_ACCEPT).
The problem is that it doesn't work. When I retrieve the attachment, it is always null. And if I set up the attachment via attach() and then immediately call attachment(), it does work. Somehow between different events, it loses its association.
I'm sorry, my code is a bit long to post here, but if you look at the comments in this thread:
link text
...You will see that some others have basically come to the same conclusion: that attach() and attachment() don't work, and never have.
Is there a trick to get it to work, or am I stuck with the evil overhead necessary of manually doing a lookup in a map EVERY TIME there is a new read event to handle?
Finally, is there a way to "wrap" SelectionKey in a new subclass that will properly handle attach() and attachment()?
Thanks!
I have successfully attached objects to SelectionKeys without any problems, but only from the same event. For example the first time I get an OP_READ, I attach an object to the SelectionKey and on subsequent reads I retrieve it, and it works fine. Maybe OP_ACCEPT and OP_READ handle different keys because they're different events, but I think the SelectionKey should be the same for the same connection... however if you make different connections even from the same IP you will get different SelectionKeys.
UPDATE: I just checked my code and there is something very important: I didn't call attach() at all; I used the SelectableChannel.register(Selector sel, int ops, Object att) method. If you do that, subsequent calls to attachment() on the SelectionKey will work.
There is no CR in your linked page, and I can't see anything on bugs.sun.com. However, attach/attachment is very simple code (although slightly more complicated after my bug. My guess is that you are getting a different SelectionKey, so trying to wrap it would be pointless.
Related
I am looking at the implementation of LogbackMDCAdapter, and it keeps track of lastOperation I don't understand the reason for doing this, anyone has an idea why this is done?
And, why duplicateAndInsertNewMap is required?
Based on the comment here the map copying is required for serialization purposes
Each time a value is added, a new instance of the map is created. This
is to be certain that the serialization process will operate on the
updated map and not send a reference to the old map, thus not allowing
the remote logback component to see the latest changes.
This refers to the behaviour of ObjectOutputStream sending references to previously written objects instead of the full object, unless using the writeUnshared method.
It is not directly obvious why it's possible to skip copying unless there's a get/put combination, but apparently even if you have multiple put operations in a row, the serialization will work properly as long as the map is copied only when a put/remove is performed right after a get. So this is a performance optimization to avoid copying the map unnecessarily when putting several items in it.
My (Android) app needs a network scanner feature.
I want to give it a subnet and I want it to send a request to each possible address on the subnet and determine whether or not it's responsive.
I have two classes:
Device, which contains an address and a property available (bool) (that can be set by the method checkAvailable).
NetworkerScanner, which extends Thread and instantiates all the Devices.
Eventually, I plan to have an object that is an observer on an Observable collection that will contain all the available devices.
Adding the available Devices to the Collection is not obvious.
Algorithm
Let col be a Observable Collection
For each possible address
Instantiate a corresponding Device
On a new, separate thread, get this new device's availability.
If it's available, then add it to col.
Checking device's availability is not immediate (I'm using Volley, which uses callbacks).
How can I, from my HTTP request callback, add the Device to the collection?
I have several ideas:
Pass a reference to the collection to the device when instantiating it, which seems like a bad idea, since the collection doesn't have a reason to be a property of the Device. More than that, if I wanted to run multiple scans on the same Device instances, it wouldn't work anymore since a Device could only have one Collection.
I could also pass a reference to the collection to the checkAvailable method, but I feel like this is a trick (and a trick of the wrong type of tricks).
When calling checkAvailable, pass a reference to an onResponseListener (the callback method for the HTTP request) to it. Since I would have created the listener in my NetworkScanner, I could capture the local collection. But I feel this is wrong. Like... very wrong.
Please suggest.
I need some help with some modification of https://github.com/playframework/play-java-websocket-example.
This example based on own Source for given Stock ID. Every Source generate new stock value in some time interval:
public Source<StockUpdate, NotUsed> update() {
return source.throttle(1, duration, 1, ThrottleMode.shaping())
.map(sq -> new StockUpdate(sq.symbol, sq.price));
}
The example in much part is what I need (the "watch/unwatch" stocks idea) so I want to use it in very similiar way but I don't want to fake stock quote time interval generator in my app because I'm connected to real, one stock exchange source.
I read messages (in other part of my app) via java.io.InputStream and, for now, I put them in java.util.Queue (java.util.concurrent.LinkedBlockingQueue) via queue.offer(message) and now I want to get it somehow from Stock.update() (however I don't know it's best place).
So far I got know that I could use for example Source.queue(BUFFER_LENGTH, OverflowStrategy.backpressure()), but it doesn't have any reference to (my) queue.
I also know that I could use Source.queue(BUFFER_LENGTH, OverflowStrategy.backpressure()).to(...).run(...).offer(...) but unfortunatelly I don't know how to connect it in UserActor.addStock(Stock) with Flow, UniqueKillSwitch, etc.
Maybe someone needed modifications like me and could give some hints?
So far I got know that I could use for example Source.queue(BUFFER_LENGTH, OverflowStrategy.backpressure()), but it doesn't have any reference to (my) queue
You could change your code so it uses the Source.queue instead of the java.util.Queue. Alternatively you could have a thread to read from your queue and push it to the Source.queue.
I'm looking for something similar to RemovalListener/RemovalNotification - but notification of when values in the cache are modified. Notification would include the old value, as well as the new value that has just been added.
[update]
I only populate the cache via a CaceLoader (load & reload). The "source" of the cached elements are at times flakey (remote to the cache).
So the two primary reason for having the replacement element as well are:
Debug logging to indicate when/what values are actually retrieved
from the remote source. This one could be accomplished in a class
that does the remote retrieval.
Generate difference that can then be proactively pushed to (remote)
clients. e.g. publishing changes via blazeDS, rather than requiring
the clients to continuously "get".
It should be possible to implement this without additional notification via the reload method, and getting the current cache contents before going off and getting the new value, and then comparing the new value and the previous value - and then taking additional action. I was looking for a more generic way to decouple the modification notification.
Thanks.
You could file a Guava feature request asking for a method to be added to RemovalNotification that would return the replacement value when the cause is REPLACED. But please provide as much detail as possible about your problem and why this is a good solution for it.
I have already posted a question today. This question is about the same project but unrelated. I am developing an application for the Lego NXT Mindstorm robot. I have two robots and a GUI running on a PC.
In leJOS NXJ you can only use one input reader. This means that you can't connect the PC to two robots directly and let the two robots connect to each other directly. So this is what i have done. I have connected the PC to the two robots directly and and when the two robots want to communicate directly, i send their messages through the GUI.
There is a whole lot of communication between the GUI and the robots as well as between the robots themselves. For this reason anytime i write data to the output stream it seems that some of the data are overwritten by others and the system is not working correctly as suppose to.
I have been advice to write a class that will hold a collection(Queue) object so that anytime the robot want to send something, it add it to the collection(Queue) and from that class which hold the collection object, there will be a method so that it checks the collection constantly and whenever it is not empty, it sends the data in the collection to the output stream.
It means that whenever the data in the collection are been sent to the output stream, it is possible a new data is been added.
Some people suggested to me of using ArrayBlockQueue and etc.. but those classes are not available in the class.jar file which the robot uses.
The collections classes that i know in this jar file are Vectors and Queue.
I am asking if someone can help me by giving me ideas of how to implement such class. A method in the class will check from time to time if there are data inside the collection and it will send them through the output stream. While it is sending , it is possible that new elements are being added.
Since the data are being sent from one place, no data will overwrite the other. It sounds to me as a good idea.
All your suggestions are welcome.
Thanks.
Vector is good because (at least in JavaSE - I don't know what Mindstorms uses) it's synchronized, so all calls are atomic - if another thread tries to add something to the Vector when you're removing from it, it will block until you have finished, avoiding the issue where data can get lost.
Alternatively, you may want to have a look at the synchronization wrappers in the Collections class.
Alternatively, you could do your own implementation of a blocking queue by subclassing a standard Queue. Although more complicated, a blocking queue is a better solution, as it avoids a busy wait, where you repeatedly check the queue and are each time told it is empty.