avatar

962

Make sniping use just the identifier, to simplify things.
Make cancelling snipes entirely based on just the identifier.

by mrs, 21 Jun, 2009 10:39 AM
955 962  
358358   public void setServer(AuctionServerInterface newServer) {
359359     if(newServer != mServer) {
360360       //  "CANCEL_SNIPE #{id}"
361       if(isSniped()) getServer().cancelSnipe(this);
361       if(isSniped()) getServer().cancelSnipe(getIdentifier());
362362       mServer = newServer;
363363       if(isSniped()) getServer().setSnipe(this);
364364     }
------
12001200       }
12011201       setInteger("snipe_id", null);
12021202       mSnipe = null;
1203       getServer().cancelSnipe(this);
1203       getServer().cancelSnipe(getIdentifier());
12041204     } else {
12051205       mSnipe = AuctionSnipe.create(snipe, quantity, 0);
12061206       getServer().setSnipe(this);
------
12141214    * @brief Refresh the snipe, so it picks up a potentially changed end time, or when initially loading items.
12151215    */
12161216   public void refreshSnipe() {
1217     getServer().cancelSnipe(this);
1217     getServer().cancelSnipe(getIdentifier());
12181218     getServer().setSnipe(this);
12191219   }
12201220 
893 962  
121121 
122122   void setSnipe(AuctionEntry snipeOn);
123123 
124   void cancelSnipe(EntryInterface snipeCancel);
124   void cancelSnipe(String identifier);
125125 }
914 962  
6060   public abstract void updateHighBid(AuctionEntry ae);
6161 
6262   public abstract void setSnipe(AuctionEntry snipeOn);
63   public abstract void cancelSnipe(EntryInterface snipeCancel);
63   public abstract void cancelSnipe(String identifier);
6464 
6565 
6666   /**
956 962  
4747 
4848   /** @noinspection FieldCanBeLocal*/
4949   private TimerHandler eQueue;
50   private Map<String, AuctionQObject> snipeMap = new HashMap<String, AuctionQObject>();
5150 
5251   /**< The full amount of time it takes to request a single page from this site. */
5352   private long mPageRequestTime =0;
------
199198           return;
200199         }
201200         break;
202       case AuctionQObject.CANCEL_SNIPE:
203         cancelSnipe((EntryInterface) ac.getData());
204         return;
205       case AuctionQObject.SET_SNIPE:
206         setSnipe((AuctionEntry) ac.getData());
207         return;
208201       case AuctionQObject.BID:
209202         bidMsg(ac);
210203         return;
------
293286     MQFactory.getConcrete("Swing").enqueue("IGNORE " + configBidMsg + ' ' + bidResultString);
294287   }
295288 
289   private static final int THIRTY_SECONDS = 30 * Constants.ONE_SECOND;
290   private static final long TWO_MINUTES = Constants.ONE_MINUTE * 2;
291 
296292   public void setSnipe(AuctionEntry snipeOn) {
297     AuctionQObject currentlyExists = snipeMap.get(snipeOn.getIdentifier());
293     String identifier = snipeOn.getIdentifier();
294     Date endDate = snipeOn.getEndDate();
295     long snipeDelta = snipeOn.getSnipeTime();
298296     //  If we already have a snipe set for it, first cancel the old one, and then set up the new.
299     if(currentlyExists != null) {
300       _etqm.erase(null, currentlyExists);
301       _etqm.erase(null, snipeOn);
302       snipeMap.remove(snipeOn.getIdentifier());
303     }
297     _etqm.erase(identifier);
304298 
305     long two_minutes = Constants.ONE_MINUTE*2;
306     AuctionQObject payload = new AuctionQObject(AuctionQObject.SNIPE, new Snipe(mLogin, mBidder, snipeOn), null);
307 
308     if (snipeOn.getEndDate() != null && snipeOn.getEndDate() != Constants.FAR_FUTURE) {
309       _etqm.add(payload, mSnipeQueue, (snipeOn.getEndDate().getTime() - snipeOn.getSnipeTime()) - two_minutes);
310       _etqm.add(payload, mSnipeQueue, (snipeOn.getEndDate().getTime() - snipeOn.getSnipeTime()));
311       _etqm.add(snipeOn.getIdentifier(), "drop", snipeOn.getEndDate().getTime() + 30 * Constants.ONE_SECOND);
312       snipeMap.put(snipeOn.getIdentifier(), payload);
299     if (endDate != null && endDate != Constants.FAR_FUTURE) {
300       _etqm.add(identifier, mSnipeQueue, (endDate.getTime() - snipeDelta) - TWO_MINUTES);
301       _etqm.add(identifier, mSnipeQueue, (endDate.getTime() - snipeDelta));
302       _etqm.add(identifier, "drop",       endDate.getTime() + THIRTY_SECONDS);
313303     }
314304   }
315305 
316   public void cancelSnipe(EntryInterface snipeCancel) {
317     String identifier = snipeCancel.getIdentifier();
318     AuctionQObject cancellable = snipeMap.get(identifier);
319 
306   public void cancelSnipe(String identifier) {
320307     //  Erase the pending snipe
321     _etqm.erase(null, cancellable);
322     //  Erase the 30 seconds post-completion update
323     _etqm.erase(null, snipeCancel);
324 
325     snipeMap.remove(identifier);
308     _etqm.erase(identifier);
326309   }
327310 
328311   public ebayServer(String site, String username, String password) {
------
613596     MQFactory.getConcrete("Swing").enqueue("Done Getting Selling Items for " + userId);
614597   }
615598 
616   //  TODO -- Wouldn't it be nice if this took an item number, and looked it up, instead of keeping a reference to the actual (potentially duplicated) object?
617599   private class SnipeListener implements MessageQueue.Listener {
600     private Map<String, Snipe> mSnipeMap = new HashMap<String, Snipe>();
601 
602     /**
603      * Retrieve a stored Snipe object if one exists (containing the cookie information),
604      * or create a new one if one doesn't exist.
605      *
606      * @param identifier - The auction identifier to create the snipe for.
607      *
608      * @return - A Snipe object, either with a cookie object, or w/o. Returns
609      * null if the AuctionEntry associated with the identifier does not exist
610      * or is not sniped.
611      */
612     private Snipe getSnipe(String identifier) {
613       AuctionEntry ae = EntryCorral.getInstance().takeForRead(identifier);
614       if (ae == null || !ae.isSniped()) return null;
615 
616       Snipe snipe;
617       if (mSnipeMap.containsKey(identifier)) {
618         snipe = mSnipeMap.get(identifier);
619       } else {
620         snipe = new Snipe(mLogin, mBidder, ae);
621         mSnipeMap.put(identifier, snipe);
622       }
623       return snipe;
624     }
625 
618626     public void messageAction(Object deQ) {
619       AuctionQObject ac = (AuctionQObject) deQ;
620       if (ac.getCommand() == AuctionQObject.SNIPE) {
621         Snipe snipe = (Snipe) ac.getData();
622         int snipeResult = snipe.fire();
623         switch(snipeResult) {
624           case Snipe.RESNIPE:
625             /**
626              *  The formula for 'when' the next resnipe is, is a little complex.
627              * It's all in the code, though.  If we're 3 seconds or less away,
628              * give up.  Otherwise wait another 20% of the remaining time
629              * (minimum of 3 seconds), and retry.
630              */
631             long snipeIn = snipe.getItem().getEndDate().getTime() - _etqm.getCurrentTime();
632             if(snipeIn > Constants.THREE_SECONDS) {
633               long retry_wait = (snipeIn / 10) * 2;
634               if(retry_wait < Constants.THREE_SECONDS) retry_wait = Constants.THREE_SECONDS;
627       String identifier = (String)deQ;
628       Snipe snipe = getSnipe(identifier);
629       if(snipe == null) return;
635630 
636               _etqm.add(deQ, mSnipeQueue, _etqm.getCurrentTime()+retry_wait);
637               break;
638             }
639             //  If there are less than 3 seconds left, give up by falling through to FAIL and DONE.
640             JConfig.log().logDebug("Resnipes failed, and less than 3 seconds away.  Giving up.");
641           case Snipe.FAIL:
642             _etqm.erase(null, deQ);
643             JConfig.log().logDebug("Snipe appears to have failed; cancelling.");
644             snipe.getItem().snipeFailed();
645             //  A failed snipe is a serious, hard error, and should fall through to being removed from the snipe map.
646           case Snipe.DONE:
647             snipeMap.remove(snipe.getItem().getIdentifier());
631       int snipeResult = snipe.fire();
632       switch (snipeResult) {
633         case Snipe.RESNIPE:
634           /**
635            *  The formula for 'when' the next resnipe is, is a little complex.
636            * It's all in the code, though.  If we're 3 seconds or less away,
637            * give up.  Otherwise wait another 20% of the remaining time
638            * (minimum of 3 seconds), and retry.
639            */
640           long snipeIn = snipe.getItem().getEndDate().getTime() - _etqm.getCurrentTime();
641           if (snipeIn > Constants.THREE_SECONDS) {
642             long retry_wait = (snipeIn / 10) * 2;
643             if (retry_wait < Constants.THREE_SECONDS) retry_wait = Constants.THREE_SECONDS;
644 
645             _etqm.add(identifier, mSnipeQueue, _etqm.getCurrentTime() + retry_wait);
648646             break;
649           case Snipe.SUCCESSFUL:
650           default:
651             break;
652         }
647           }
648           //  If there are less than 3 seconds left, give up by falling through to FAIL and DONE.
649           JConfig.log().logDebug("Resnipes failed, and less than 3 seconds away.  Giving up.");
650         case Snipe.FAIL:
651           _etqm.erase(identifier);
652           JConfig.log().logDebug("Snipe appears to have failed; cancelling.");
653           snipe.getItem().snipeFailed();
654           //  A failed snipe is a serious, hard error, and should fall through to being removed from any other lists.
655         case Snipe.DONE:
656           mSnipeMap.remove(identifier);
657           break;
658         case Snipe.SUCCESSFUL:
659         default:
660           break;
653661       }
654662     }
655663   }
893 962  
1616   public static final int BID = 5;
1717   public static final int LOAD_TITLE = 6;
1818   public static final int LOAD_STRINGS = 7;
19   public static final int SET_SNIPE = 8;
20   public static final int SNIPE = 9;
21   public static final int CANCEL_SNIPE = 10;
2219 
2320   public AuctionQObject() { super(); }
2421