修改增加上传量下载量逻辑

Change-Id: I5dc30fd08feabca1e2acffb647966e4060d76bd3
diff --git a/src/main/java/tracker/Tracker.java b/src/main/java/tracker/Tracker.java
index 008ac4a..1ac4d94 100644
--- a/src/main/java/tracker/Tracker.java
+++ b/src/main/java/tracker/Tracker.java
@@ -4,20 +4,19 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
-import java.util.HashMap;
-import java.util.Map;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityTransaction;
-import javax.persistence.Persistence;
-import com.querydsl.jpa.impl.JPAUpdateClause;
-import entity.QUserPT;
-import entity.Seed;
-import entity.SeedDownload;
-import entity.TransRecord;
-import entity.config;
-import entity.TTorent;
+import java.security.MessageDigest;
 import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.persistence.*;
+import com.dampcake.bencode.Bencode;
+import com.dampcake.bencode.Type;
+import com.querydsl.jpa.impl.JPAUpdateClause;
+import entity.*;
+import entity.config;
+
 public class Tracker implements TrackerInterface {
     private final EntityManagerFactory emf;
     // 默认构造:产线数据库
@@ -35,85 +34,190 @@
         this.emf = emf;
     }
     @Override
-    public boolean AddUpLoad(String userid, int upload) {
+    public boolean AddUpLoad(String userid, int upload, String infoHash) {
+        long newTotal = upload;  // convert to long
         EntityManager em = emf.createEntityManager();
         EntityTransaction tx = em.getTransaction();
+        tx.begin();
         try {
-            tx.begin();
-            QUserPT q = QUserPT.userPT;
-            long updated = new JPAUpdateClause(em, q)
-                .where(q.userid.eq(userid))
-                .set(q.upload, q.upload.add(upload))
-                .execute();
+            // 1) find the seedId by infoHash
+            String seedId = em.createQuery(
+                "SELECT s.seedId FROM SeedHash s WHERE s.infoHash = :ih", String.class)
+                .setParameter("ih", infoHash)
+                .getSingleResult();
+            // 2) sum existing uploads for this user+seed
+            Long sumSoFar = em.createQuery(
+                "SELECT COALESCE(SUM(t.upload),0) FROM TransRecord t WHERE t.uploaduserid = :uid AND t.seedid = :sid",
+                Long.class)
+                .setParameter("uid", userid)
+                .setParameter("sid", seedId)
+                .getSingleResult();
+            long delta = newTotal - sumSoFar;
+            if (delta < 0L) {
+                tx.rollback();
+                return true;   // error: newTotal less than already recorded
+            }
+            if (delta == 0L) {
+                tx.rollback();
+                return false;  // nothing to do
+            }
+            // 3) persist a new TransRecord with only the delta
+            TransRecord rd = new TransRecord();
+            rd.taskid       = UUID.randomUUID().toString();
+            rd.uploaduserid = userid;
+            rd.seedid       = seedId;
+            rd.upload       = delta;
+            rd.maxupload    = newTotal;
+            em.persist(rd);
+
+            // 4) 重新计算用户的总上传,确保与 TransRecord 完全一致
+            Long totalUpload = em.createQuery(
+                "SELECT COALESCE(SUM(t.upload),0) FROM TransRecord t WHERE t.uploaduserid = :uid",
+                Long.class
+            )
+            .setParameter("uid", userid)
+            .getSingleResult();
+            UserPT user = em.find(UserPT.class, userid);
+            user.upload = totalUpload;
+            em.merge(user);
             tx.commit();
-            // 成功时 updated>0 返回 false,失败时返回 true
-            return updated <= 0;
-        } catch(Exception e) {
+            return false;      // success
+        } catch (RuntimeException ex) {
             if (tx.isActive()) tx.rollback();
-            return true;
+            throw ex;
         } finally {
             em.close();
         }
     }
+    
     @Override
     public boolean ReduceUpLoad(String userid, int upload){
+        long uploadLong = upload;  // convert to long
         EntityManager em = emf.createEntityManager();
         EntityTransaction tx = em.getTransaction();
+        tx.begin();
         try {
-            tx.begin();
-            QUserPT q = QUserPT.userPT;
-            long updated = new JPAUpdateClause(em, q)
-                .where(q.userid.eq(userid))
-                .set(q.upload, q.upload.subtract(upload))
-                .execute();
+            // 1) fetch user and ensure enough upload to reduce
+            UserPT user = em.find(UserPT.class, userid);
+            long before = user.upload;
+            if (uploadLong > before) {
+                tx.rollback();
+                return true;   // error: cannot reduce more than current total
+            }
+            // 2) subtract
+            user.upload = before - uploadLong;
+            em.merge(user);
+            // (optional) record a negative TransRecord so sums stay in sync
+            TransRecord rd = new TransRecord();
+            rd.taskid       = UUID.randomUUID().toString();
+            rd.uploaduserid = userid;
+            rd.seedid       = null;
+            rd.upload       = -uploadLong;
+            rd.maxupload    = user.upload;
+            em.persist(rd);
             tx.commit();
-            // 成功时 updated>0 返回 false,失败时返回 true
-            return updated <= 0;
-        } catch(Exception e) {
+            return false;      // success
+        } catch (RuntimeException ex) {
             if (tx.isActive()) tx.rollback();
-            return true;
+            throw ex;
         } finally {
             em.close();
         }
     }
     @Override
-    public boolean AddDownload(String userid, int download) {
+    public boolean AddDownload(String userid, int download, String infoHash) {
+        long newTotal = download;  // convert to long
         EntityManager em = emf.createEntityManager();
         EntityTransaction tx = em.getTransaction();
         try {
-            tx.begin();
-            QUserPT q = QUserPT.userPT;
-            long updated = new JPAUpdateClause(em, q)
-                .where(q.userid.eq(userid))
-                .set(q.download, q.download.add(download))
-                .execute();
-            tx.commit();
-            return updated <= 0;
-        } catch(Exception e) {
-            if (tx.isActive()) tx.rollback();
+            // 1. 查 SeedHash
+            TypedQuery<SeedHash> qsh = em.createQuery(
+                "SELECT s FROM SeedHash s WHERE s.infoHash = :h", SeedHash.class);
+            qsh.setParameter("h", infoHash);
+            List<SeedHash> shl = qsh.getResultList();
+            if (shl.isEmpty()) {
+                System.out.println("seed没有被记录");
+                return true;
+            }
+            String seedid = shl.get(0).seedId;
+
+            // 2. 统计该用户在该种子上的已有 download
+            TypedQuery<Long> qsum = em.createQuery(
+                "SELECT COALESCE(SUM(t.download),0) FROM TransRecord t " +
+                "WHERE t.seedid = :sid AND t.downloaduserid = :uid", Long.class);
+            qsum.setParameter("sid", seedid);
+            qsum.setParameter("uid", userid);
+            long oldSeedSum = qsum.getSingleResult();
+
+            long diff = newTotal - oldSeedSum;
+            if (diff <= 0) return false;
+            
+            System.out.println("AddDownload: 该种子原有总量=" + oldSeedSum + ", 新总量=" + newTotal + ", 增量=" + diff);
+
+            try {
+                tx.begin();
+                // 1. persist 增量记录
+                TransRecord tr = new TransRecord();
+                tr.taskid         = UUID.randomUUID().toString();
+                tr.downloaduserid = userid;
+                tr.seedid         = seedid;
+                tr.download       = diff;
+                tr.maxdownload    = newTotal;
+                em.persist(tr);
+
+                // 2. 全表重新累计该用户所有种子的 download,并更新 UserPT.download
+                TypedQuery<Long> qTotal = em.createQuery(
+                    "SELECT COALESCE(SUM(t.download),0) FROM TransRecord t WHERE t.downloaduserid = :uid",
+                    Long.class
+                )
+                .setParameter("uid", userid);
+                long userTotalDownload = qTotal.getSingleResult();
+                QUserPT quser = QUserPT.userPT;
+                new JPAUpdateClause(em, quser)
+                    .where(quser.userid.eq(userid))
+                    .set(quser.download, userTotalDownload)
+                    .execute();
+
+                tx.commit();
+                return false;
+            } catch (Exception e) {
+                if (tx.isActive()) tx.rollback();
+                return true;
+            } finally {
+                em.close();
+            }
+        } catch (Exception e) {
             return true;
-        } finally {
-            em.close();
         }
     }
     @Override
     public boolean ReduceDownload(String userid, int download) {
+        long downloadLong = download;  // convert to long
         EntityManager em = emf.createEntityManager();
-        EntityTransaction tx = em.getTransaction();
         try {
+            // 1. 预检查当前值
+            TypedQuery<Long> qcurr = em.createQuery(
+                "SELECT u.download FROM UserPT u WHERE u.userid = :uid", Long.class);
+            qcurr.setParameter("uid", userid);
+            long current = qcurr.getSingleResult();
+            if (downloadLong > current) {
+                em.close();
+                return true;
+            }
+            // 2. 执行减法更新
+            EntityTransaction tx = em.getTransaction();
             tx.begin();
             QUserPT q = QUserPT.userPT;
-            long updated = new JPAUpdateClause(em, q)
+            new JPAUpdateClause(em, q)
                 .where(q.userid.eq(userid))
-                .set(q.download, q.download.subtract(download))
+                .set(q.download, q.download.subtract(downloadLong))
                 .execute();
             tx.commit();
-            return updated <= 0;
+            return false;
         } catch(Exception e) {
-            if (tx.isActive()) tx.rollback();
             return true;
         } finally {
-            em.close();
+            if (em.isOpen()) em.close();
         }
     }
     @Override
@@ -166,6 +270,26 @@
             String filename = TTorent.getName();
             Path target = storageDir.resolve(seedid + "_" + filename);
             Files.copy(TTorent.toPath(), target, StandardCopyOption.REPLACE_EXISTING);
+
+            // attempt to parse infoHash, but don’t fail if parsing fails
+            String infoHash = null;
+            try {
+                byte[] torrentData = Files.readAllBytes(target);
+                Bencode bencode = new Bencode();
+                @SuppressWarnings("unchecked")
+                Map<String,Object> meta = (Map<String,Object>) bencode.decode(torrentData, Type.DICTIONARY);
+                byte[] infoBytes = bencode.encode((Map<String,Object>) meta.get("info"));
+                MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
+                byte[] digest = sha1.digest(infoBytes);
+                StringBuilder sb = new StringBuilder();
+                for (byte b1 : digest) {
+                    sb.append(String.format("%02x", b1));
+                }
+                infoHash = sb.toString();
+            } catch (Exception e) {
+                System.err.println("Warning: could not parse torrent infoHash: " + e.getMessage());
+            }
+
             EntityManager em = emf.createEntityManager();
             EntityTransaction tx = em.getTransaction();
             try {
@@ -173,6 +297,14 @@
                 Seed seed = em.find(Seed.class, seedid);
                 seed.url = target.toString();
                 em.merge(seed);
+
+                // upsert SeedHash only if we have a valid infoHash
+                if (infoHash != null) {
+                    SeedHash sh = new SeedHash();
+                    sh.seedId = seedid;
+                    sh.infoHash = infoHash;
+                    em.merge(sh);
+                }
                 tx.commit();
                 return 0;
             } catch (Exception e) {
@@ -224,7 +356,7 @@
             tx.begin();
             em.persist(rd);
             tx.commit();
-            // 持久化成功,返回1表示插入成功
+            // 返回1表示插入成功
             return 1;
         } catch (Exception e) {
             if (tx.isActive()) tx.rollback();