Results 1 to 10 of 17

Hybrid View

  1. #1
    Senior Member
    Join Date
    Sep 2013
    Location
    Coimbatore
    Posts
    74

    Issue on deleting stocks from adapter

    I have some issue on my adapter. But my server code working properly. Some times adapter showing old data in user page. Some times it comes and disappear, and in some case now my server shows only 2 rows but adapter having 3 stock rows and displaying 3 rows in user page. But extra one row is too old data and deleted from server also. Even though it showing in adapter. If I restart the LS it working fine, but after some times again this issue comes and I need to restart the server. I couldn't find the reason and issue for this.
    I'm using the following code,


    private final HashMap<String, RateRow> liveratesnew = new HashMap<String, RateRow>();
    private final HashMap<String, RateRow> liveratesold = new HashMap<String, RateRow>();


    synchronized (liveratesnew) {
    if ((liveratesnew.size() != liveratesold.size())) {
    if (liveratesnew.size() > liveratesold.size()) {
    synchronized (liveratesold) {
    liveratesnew.forEach((k, v) -> {
    if (!liveratesold.containsKey(liveratesnew.get(k).get ItemName())) {
    liveratesold.put(liveratesnew.get(k).getItemName() , v);
    final HashMap<String, String> liverateevent = new HashMap<String, String>();
    liverateevent.put("key", liveratesnew.get(k).getItemName());
    liverateevent.put("desc", liveratesnew.get(k).getInstrumentName());
    liverateevent.put("bid", liveratesnew.get(k).getBidRate());
    liverateevent.put("ask", liveratesnew.get(k).getAskRate());
    listener.onActualStatus(liveratesnew.get(k).getIte mName(), liverateevent,
    false, 1);
    }
    });
    }
    } else if (liveratesnew.size() < liveratesold.size()) {
    final HashMap<String, String> removeoldkey = new HashMap<String, String>();
    synchronized (liveratesold) {
    for (Entry<String, RateRow> e : liveratesold.entrySet()) {
    String key = e.getKey();
    if (!liveratesnew.containsKey(liveratesold.get(key))) {
    listener.onDeleteStatus(liveratesold.get(key).getI temName());
    removeoldkey.put(key, liveratesold.get(key).getItemName());
    // liveratesold.remove(liveratesold.get(key).getItemN ame());


    }
    }
    }


    for (Entry<String, String> e : removeoldkey.entrySet()) {
    String key = e.getKey();
    // listener.onDeleteStatus(key);
    liveratesold.remove(key);
    }
    removeoldkey.clear();


    }
    }
    }

  2. #2
    Administrator
    Join Date
    Feb 2008
    Location
    Siracusa
    Posts
    152
    Hi rvkvino,

    it's very hard to understand what is going on from the code you shown, as it its not clear where it is located inside your adapter.
    That said, at first glance it seems that you are running against some race conditions, as you are checking liveratesold.size() outside the synchronized blocks on which it could be modified.

    Try to move size checks inside synchronized blocks and get back to us.

    Gianluca

  3. #3
    Senior Member
    Join Date
    Sep 2013
    Location
    Coimbatore
    Posts
    74
    public class ExternalFeedSimulator {
    private static final Timer dispatcher = new Timer();
    private final String REMOTE_RATE_FEED_URL = "serverurl";
    private final ArrayList<RateRow> liverates = new ArrayList<RateRow>();
    private final HashMap<String, RateRow> liveratesnew = new HashMap<String, RateRow>();
    private final HashMap<String, RateRow> liveratesold = new HashMap<String, RateRow>();
    private ExternalFeedListener listener;


    public void start() {
    sendGet();
    // long waitTime = displayrates.computeNextWaitTime();
    long waitTime = 500;
    liveratescheduleGenerator(liverates, waitTime);
    }


    // HTTP GET request
    public void sendGet() {
    String url = REMOTE_RATE_FEED_URL;
    URL obj;
    try {
    obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();


    // optional default is GET
    con.setRequestMethod("GET");


    // add request header
    con.setRequestProperty("User-Agent", USER_AGENT);


    // int responseCode = con.getResponseCode();


    // System.out.println("Response Code : " + responseCode);


    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();


    while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
    }
    in.close();


    if (response.toString() == null || response.toString().equals(""))
    return;
    String strlowerresponse = response.toString();


    String trade_type = getItemValue(strlowerresponse, "trade_type");
    String rate_display = getItemValue(strlowerresponse, "rate_display");
    String update_time = getItemValue(strlowerresponse, "gold_updatetime");
    String market_closed_msg = "";
    String commodityupdatetime = getItemValue(strlowerresponse, "commodityupdatetime");


    trade_type = trade_type.trim();
    int startIndex = 0;
    liveratesnew.clear();
    while (startIndex != -1) {
    int item_start_pos = strlowerresponse.indexOf("<Commodity>", startIndex) + 11;
    if (item_start_pos < 11)
    break;
    int item_end_pos = strlowerresponse.indexOf("</Commodity>", item_start_pos + 1);
    if (item_end_pos <= -1)
    break;
    String strnode = strlowerresponse.substring(item_start_pos, item_end_pos);
    String instrid = getItemValue(strnode, "id");
    String instrname = getItemValue(strnode, "name");
    String strsellrate = getItemValue(strnode, "selling_rate");
    String strbuyrate = getItemValue(strnode, "buying_rate");
    String strhighrate = getItemValue(strnode, "selling_high");
    String strlowrate = getItemValue(strnode, "selling_low");


    int ordernumber = Integer.parseInt(getItemValue(strnode, "ordernumber"));
    if (strbuyrate.equalsIgnoreCase("") || strbuyrate.equalsIgnoreCase("0"))
    strbuyrate = "-";
    if (strsellrate.equalsIgnoreCase("") || strsellrate.equalsIgnoreCase("0"))
    strsellrate = "-";
    RateRow commrate = new RateRow("Item" + instrid, instrname, strbuyrate, strsellrate, strlowrate,
    strhighrate, ordernumber);


    liverates.add(commrate);
    liveratesnew.put("Item" + instrid, commrate);
    startIndex = item_end_pos;
    }


    if (trade_type.equalsIgnoreCase("3") || rate_display.equalsIgnoreCase("1")) {
    rate_display = "0";
    } else {
    rate_display = "1";
    }
    RateRow marketstatus = new RateRow("Marketstatus", rate_display, commodityupdatetime, update_time,
    market_closed_msg);
    curmarketstatus.add(marketstatus);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (NumberFormatException e) {
    System.out.println("not a number");
    }
    }


    public synchronized void removeListener() {
    // remove the listener
    this.listener = null;
    }


    public String getItemValue(String strdata, String query) {
    String strlowerdata = strdata.toLowerCase();
    query = query.toLowerCase();
    int item_start_pos = strlowerdata.indexOf("<" + query + ">") + query.length() + 2;
    if (item_start_pos < query.length() + 2)
    return "";
    int item_end_pos = strlowerdata.indexOf("</" + query + ">");
    if (item_end_pos < query.length() + 2)
    return "";


    String item_value = strdata.substring(item_start_pos, item_end_pos);
    item_value = item_value.trim();
    return item_value;
    }


    private void currentmarketstatusscheduleGenerator(final ArrayList<RateRow> nmarketstatus, long waitTime) {
    dispatcher.schedule(new TimerTask() {
    @Override
    public void run() {
    long nextWaitTime;
    synchronized (nmarketstatus) {
    if (listener != null) {
    for (RateRow marketstatus : nmarketstatus) {
    final HashMap<String, String> markstatus = new HashMap<String, String>();
    markstatus.put("desc", marketstatus.getInstrumentName());
    markstatus.put("ratedisplay", marketstatus.getBidRate());
    markstatus.put("comupdatetime", marketstatus.getAskRate());
    markstatus.put("updatetime", marketstatus.getLow_price());
    markstatus.put("msg", marketstatus.getHigh_price());
    listener.onEvent(marketstatus.getInstrumentName(), markstatus, false);
    }
    }
    nmarketstatus.clear();
    nextWaitTime = 500;
    }


    currentmarketstatusscheduleGenerator(curmarketstat us, nextWaitTime);
    }
    }, waitTime);
    }
    private void liveratescheduleGenerator(final ArrayList<RateRow> displayrates, long waitTime) {
    dispatcher.schedule(new TimerTask() {
    @Override
    public void run() {
    long nextWaitTime;
    synchronized (displayrates) {
    if (listener != null) {
    for (RateRow curbidaskrates : displayrates) {
    final HashMap<String, String> bidaskevent = new HashMap<String, String>();
    bidaskevent.put("key", curbidaskrates.getItemName());
    bidaskevent.put("desc", curbidaskrates.getInstrumentName());
    bidaskevent.put("bid", curbidaskrates.getBidRate());
    bidaskevent.put("ask", curbidaskrates.getAskRate());
    bidaskevent.put("low", curbidaskrates.getLow_price());
    bidaskevent.put("high", curbidaskrates.getHigh_price());
    bidaskevent.put("order", Integer.toString(curbidaskrates.getDisplayorder()) );
    listener.onActualStatus(curbidaskrates.getItemName (), bidaskevent, false, 2);
    // listener.onEvent(curbidaskrates.getItemName(),
    // bidaskevent, false);
    }


    }
    displayrates.clear();
    nextWaitTime = 500;


    synchronized (liveratesnew) {
    if ((liveratesnew.size() != liveratesold.size())) {
    if (liveratesnew.size() > liveratesold.size()) {
    synchronized (liveratesold) {
    liveratesnew.forEach((k, v) -> {
    if (!liveratesold.containsKey(liveratesnew.get(k).get ItemName())) {
    liveratesold.put(liveratesnew.get(k).getItemName() , v);
    final HashMap<String, String> liverateevent = new HashMap<String, String>();
    liverateevent.put("key", liveratesnew.get(k).getItemName());
    liverateevent.put("desc", liveratesnew.get(k).getInstrumentName());
    liverateevent.put("bid", liveratesnew.get(k).getBidRate());
    liverateevent.put("ask", liveratesnew.get(k).getAskRate());
    liverateevent.put("low", liveratesnew.get(k).getLow_price());
    liverateevent.put("high", liveratesnew.get(k).getHigh_price());
    liverateevent.put("order",
    Integer.toString(liveratesnew.get(k).getDisplayord er()));
    listener.onActualStatus(liveratesnew.get(k).getIte mName(), liverateevent,
    false, 1);
    }
    });
    }
    } else if (liveratesnew.size() < liveratesold.size()) {

    final HashMap<String, String> removeoldkey = new HashMap<String, String>();
    synchronized (liveratesold) {
    for (Entry<String, RateRow> e : liveratesold.entrySet()) {
    String key = e.getKey();
    if (!liveratesnew.containsKey(liveratesold.get(key))) {
    listener.onDeleteStatus(liveratesold.get(key).getI temName());
    removeoldkey.put(key, liveratesold.get(key).getItemName());
    // liveratesold.remove(liveratesold.get(key).getItemN ame());


    }
    }
    }


    for (Entry<String, String> e : removeoldkey.entrySet()) {
    String key = e.getKey();
    // listener.onDeleteStatus(key);
    liveratesold.remove(key);
    }
    removeoldkey.clear();


    }
    }
    }


    }
    sendGet();
    liveratescheduleGenerator(liverates, nextWaitTime);
    }
    }, waitTime);
    }


    public void setFeedListener(ExternalFeedListener listener) {
    this.listener = listener;
    }


    public void sendRates(String itemName) {
    liveratesnew.forEach((k, v) -> {
    final RateRow liverate = liveratesnew.get(k);
    if (liverate.getItemName().contains(itemName)) {
    dispatcher.schedule(new TimerTask() {
    @Override
    public void run() {
    synchronized (liverate) {
    final HashMap<String, String> crates = new HashMap<String, String>();
    crates.put("key", liverate.getItemName());
    crates.put("desc", liverate.getInstrumentName());
    crates.put("bid", liverate.getBidRate());
    crates.put("ask", liverate.getAskRate());
    crates.put("low", liverate.getLow_price());
    crates.put("high", liverate.getHigh_price());
    crates.put("order", Integer.toString(liverate.getDisplayorder()));
    listener.onActualStatus(liverate.getItemName(), crates, true, 1);
    }
    }
    }, 0);
    }


    });
    }
    }

  4. #4
    Administrator
    Join Date
    Feb 2008
    Location
    Siracusa
    Posts
    152
    Hi rvkvino,

    please try to remove possible race conditions as pointed out earlier; after that, we will evaluate whether to proceed with code inspection.

    Thanks and Regards,
    Gianluca

  5. #5
    Senior Member
    Join Date
    Sep 2013
    Location
    Coimbatore
    Posts
    74
    As You have mentioned I have checked the code many times and I have return the size checking code inside the synchronized blocks only. This issue not happening all the times. Some of the times only this issue happening and I need to restart the LS server then only get it work properly.

  6. #6
    Administrator
    Join Date
    Feb 2008
    Location
    Siracusa
    Posts
    152
    Ok rkvino,

    we need the LS server log to investigate the issue. Before that, please update lighstreamer_log_conf.xml as follows:

    <logger name="LightstreamerLogger.subscriptions" level="DEBUG"/>
    <logger name="LightstreamerLogger.pump" level="DEBUG"/>

    and try to reproduce the problem.

    Then, send the log file to support@lightstreamer.com.

    Most important, please precisely describe what you are expecting in terms of rows to be displayed, providing us with a simple example of real data.

    Thanks
    Gianluca

  7. #7
    Senior Member
    Join Date
    Sep 2013
    Location
    Coimbatore
    Posts
    74
    Fir listener.onDeleteStatus I have return code like below in my DataAdapter

    @Override
    public void onDeleteStatus(String itemName) {
    SubscriptionInfo si;
    synchronized (subscribedItems) {
    si = new SubscriptionInfo(new Boolean(false), new Boolean(true));
    subscribedItems.remove(itemName, si);
    onDelete(this.handle, itemName);
    }
    }

  8. #8
    Administrator
    Join Date
    Jul 2006
    Location
    Milan
    Posts
    973
    The code shown is still internal to your Data Adapter and does not reference anything in Lightstreamer Adapter interface.
    I mean that SubscriptionInfo, subscribedItems, and onDelete are still defined in your code.
    So, it is difficult for us to devise any needed change.
    This is furtherly complicated by the fact that the code is inspired in part to our StockQuotesDataAdapter.java code sample (which defines SubscriptionInfo and subscribedItems) and in part by the PortfolioDataAdapter.java code sample (which defines onDelete).

    Anyway, if you manage to invoke onDelete and the implementation of onDelete is the one included in our PortfolioDataAdapter.java, this should correctly send the DELETE command.
    However, we didn't see that reported in the log.
    So, please debug your Adapter to ensure that
    • onDelete is invoked,
    • onDelete invokes listener.smartUpdate with the correct parameters,
    • after the invocation, the Server logs the update as expected (on LightstreamerLogger.subscriptions at DEBUG level).

    If you dump the parameters upon the invocation of listener.smartUpdate, together with the current time, we can help you in comparing those with the log.

  9. #9
    Senior Member
    Join Date
    Sep 2013
    Location
    Coimbatore
    Posts
    74
    Hi,
    I have updated code to clear snapshot while I delete the stock the below code will execute. After I cleared the snapshot still the deleted commodity displaying in client screen. Is there any other storage available in LS.

    public void clearStatus() {
    synchronized (subscribedItems) {
    Set<String> keys = subscribedItems.keySet();
    for (String itemName : keys) {
    listener.clearSnapshot(itemName);
    }
    }
    }

    @Override
    public void onDeleteStatus(String itemName) {
    SubscriptionInfo si;
    synchronized (subscribedItems) {
    si = new SubscriptionInfo(new Boolean(false), new Boolean(true));
    subscribedItems.remove(itemName, si);
    onDelete(this.handle, itemName);
    clearStatus();
    }
    }

  10. #10
    Administrator
    Join Date
    Feb 2012
    Location
    Milano
    Posts
    538
    Hi rvkvino,

    I am not sure that the piece of code you posted, can work since the clearStatus method is called after the itemName is removed from the subscribedItems map.
    Maybe there is some confusion between the COMMAND table keys and the ItemName representing the whole table.
    While DELETE commands are executed on individual row keys, clearStatus must specify the name of the Item of entire table, the one you received with subscribe call.

    Regards,
    Giuseppe

 

 

Similar Threads

  1. Replies: 4
    Last Post: October 24th, 2011, 09:33 AM
  2. TIBCO AMS-GI data adapter issue
    By ganeshk in forum Adapter APIs
    Replies: 1
    Last Post: September 22nd, 2010, 06:52 PM
  3. Replies: 3
    Last Post: January 7th, 2010, 08:57 AM
  4. Replies: 4
    Last Post: January 3rd, 2010, 08:03 AM
  5. Problem running JMS stocks demo
    By mnenchev in forum General
    Replies: 3
    Last Post: August 10th, 2009, 03:22 PM

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
All times are GMT +1. The time now is 03:54 PM.