Browse Source

Improvements to fix freeze form/slow process on TAccountsNumbersList

Pascal Coin 4 years ago
parent
commit
b28f7b6f2e

+ 15 - 10
src/core/UNetProtocol.pas

@@ -3397,7 +3397,7 @@ end;
 procedure TNetConnection.DoProcess_GetPubkeyAccounts_Request(HeaderData: TNetHeaderData; DataBuffer: TStream);
 procedure TNetConnection.DoProcess_GetPubkeyAccounts_Request(HeaderData: TNetHeaderData; DataBuffer: TStream);
 Const CT_Max_Accounts_per_call = 1000;
 Const CT_Max_Accounts_per_call = 1000;
 var responseStream, accountsStream : TMemoryStream;
 var responseStream, accountsStream : TMemoryStream;
-  start,max : Integer;
+  start,max,i : Integer;
   c, nAccounts : Cardinal;
   c, nAccounts : Cardinal;
   acc : TAccount;
   acc : TAccount;
   DoDisconnect : Boolean;
   DoDisconnect : Boolean;
@@ -3405,6 +3405,7 @@ var responseStream, accountsStream : TMemoryStream;
   pubKey : TAccountKey;
   pubKey : TAccountKey;
   sbakl : TSafeboxPubKeysAndAccounts;
   sbakl : TSafeboxPubKeysAndAccounts;
   ocl : TAccountsNumbersList;
   ocl : TAccountsNumbersList;
+  LAccountsList : TList<Integer>;
 begin
 begin
   {
   {
   This call is used to obtain Accounts used by a Public key
   This call is used to obtain Accounts used by a Public key
@@ -3451,15 +3452,19 @@ begin
     if Assigned(sbakl) then begin
     if Assigned(sbakl) then begin
       ocl := sbakl.GetAccountsUsingThisKey(pubKey);
       ocl := sbakl.GetAccountsUsingThisKey(pubKey);
       if Assigned(ocl) then begin
       if Assigned(ocl) then begin
-        while (start<ocl.Count) And (max>0) do begin
-          acc := TNode.Node.GetMempoolAccount(ocl.Get(start));
-          if (HeaderData.protocol.protocol_available>9) then
-            TAccountComp.SaveAccountToAStream(accountsStream,acc,CT_PROTOCOL_5)
-          else
-            TAccountComp.SaveAccountToAStream(accountsStream,acc,CT_PROTOCOL_4);
-          inc(nAccounts);
-          inc(start);
-          dec(max);
+        LAccountsList := TList<Integer>.Create;
+        try
+          ocl.FillList(start,max,LAccountsList);
+          for i := 0 to LaccountsList.Count-1 do begin
+            acc := TNode.Node.GetMempoolAccount(LAccountsList[i]);
+            if (HeaderData.protocol.protocol_available>9) then
+              TAccountComp.SaveAccountToAStream(accountsStream,acc,CT_PROTOCOL_5)
+            else
+              TAccountComp.SaveAccountToAStream(accountsStream,acc,CT_PROTOCOL_4);
+          end;
+          nAccounts := LaccountsList.Count;
+        finally
+          LaccountsList.Free;
         end;
         end;
       end;
       end;
       // Save & send
       // Save & send

+ 32 - 0
src/core/UPCOrderedLists.pas

@@ -56,6 +56,8 @@ Type
     Procedure Disable;
     Procedure Disable;
     Procedure Enable;
     Procedure Enable;
     Function ToArray : TCardinalsArray;
     Function ToArray : TCardinalsArray;
+    function FillList(AStartIndex, ACount : Integer; const AList : TList<Cardinal>) : Integer; overload;
+    function FillList(AStartIndex, ACount : Integer; const AList : TList<Integer>) : Integer; overload;
   End;
   End;
 
 
 
 
@@ -180,6 +182,36 @@ begin
   if (FDisabledsCount=0) And (FModifiedWhileDisabled) then NotifyChanged;
   if (FDisabledsCount=0) And (FModifiedWhileDisabled) then NotifyChanged;
 end;
 end;
 
 
+function TOrderedCardinalList.FillList(AStartIndex, ACount : Integer; const AList : TList<Cardinal>) : Integer;
+var i : Integer;
+begin
+  AList.Clear;
+  AList.Capacity := ACount;
+  if (AStartIndex=0) and (ACount=FOrderedList.Count) then begin
+    AList.InsertRange(AStartIndex,FOrderedList);
+  end else begin
+    while (ACount>0) and (AStartIndex < FOrderedList.Count) do begin
+      AList.Add( FOrderedList.Items[AStartIndex] );
+      Inc(AStartIndex);
+      Dec(ACount);
+    end;
+  end;
+  Result := AList.Count;
+end;
+
+function TOrderedCardinalList.FillList(AStartIndex, ACount: Integer; const AList: TList<Integer>): Integer;
+var i : Integer;
+begin
+  AList.Clear;
+  AList.Capacity := ACount;
+  while (ACount>0) and (AStartIndex < FOrderedList.Count) do begin
+    AList.Add( FOrderedList.Items[AStartIndex] );
+    Inc(AStartIndex);
+    Dec(ACount);
+  end;
+  Result := AList.Count;
+end;
+
 function TOrderedCardinalList.Find(const Value: Cardinal; var Index: Integer): Boolean;
 function TOrderedCardinalList.Find(const Value: Cardinal; var Index: Integer): Boolean;
 var L, H, I: Integer;
 var L, H, I: Integer;
   C : Int64;
   C : Int64;

+ 24 - 12
src/core/UPCRPCFindAccounts.pas

@@ -152,6 +152,7 @@ var
   LAccPubKey : TAccountKey;
   LAccPubKey : TAccountKey;
   LOutput : TPCJSONArray;
   LOutput : TPCJSONArray;
   LStartsWith : TOrderedRawList;
   LStartsWith : TOrderedRawList;
+  LAccountsList : TList<Integer>;
 begin
 begin
   // Get Parameters
   // Get Parameters
   Result := False;
   Result := False;
@@ -277,21 +278,32 @@ begin
     end;
     end;
   end else begin
   end else begin
     // Search by type-forSale-balance
     // Search by type-forSale-balance
-    i := LStart;
-    while (Not ASender.Terminated) And (i < LEnd) do begin
-      if (LSearchByPubkey) then begin
-        if (i>=LAccountsNumbersList.Count) then Break;
-        LAccount := ASender.Node.GetMempoolAccount( LAccountsNumbersList.Get(i) );
-      end else begin
-        LAccount := ASender.Node.GetMempoolAccount(i);
+    if (LSearchByPubkey) then begin
+      LAccountsList := TList<Integer>.Create;
+      try
+        LAccountsNumbersList.FillList(LStart,LEnd-LStart+1,LAccountsList);
+        for i := 0 to LAccountsList.Count-1 do begin
+          LAccount := ASender.Node.GetMempoolAccount( LAccountsList[i] );
+          if (_IsValidAccount(LAccount)) then begin
+            TPascalCoinJSONComp.FillAccountObject(LAccount,LOutput.GetAsObject(LOutput.Count));
+            if LOutput.Count>=LMax then break;
+          end;
+        end;
+      finally
+        LAccountsList.Free;
       end;
       end;
+    end else begin
+      i := LStart;
+      while (Not ASender.Terminated) And (i < LEnd) do begin
+        LAccount := ASender.Node.GetMempoolAccount(i);
 
 
-      if (_IsValidAccount(LAccount)) then begin
-        TPascalCoinJSONComp.FillAccountObject(LAccount,LOutput.GetAsObject(LOutput.Count));
-        if LOutput.Count>=LMax then break;
-      end;
-      inc(i);
+        if (_IsValidAccount(LAccount)) then begin
+          TPascalCoinJSONComp.FillAccountObject(LAccount,LOutput.GetAsObject(LOutput.Count));
+          if LOutput.Count>=LMax then break;
+        end;
+        inc(i);
 
 
+      end;
     end;
     end;
   end;
   end;
   Result := True;
   Result := True;

+ 44 - 19
src/core/URPC.pas

@@ -2715,6 +2715,7 @@ Var c,c2,c3 : Cardinal;
   jsonarr : TPCJSONArray;
   jsonarr : TPCJSONArray;
   jso : TPCJSONObject;
   jso : TPCJSONObject;
   LRPCProcessMethod : TRPCProcessMethod;
   LRPCProcessMethod : TRPCProcessMethod;
+  LAccountsList : TList<Integer>;
 begin
 begin
   _ro := Nil;
   _ro := Nil;
   _ra := Nil;
   _ra := Nil;
@@ -2769,13 +2770,15 @@ begin
       Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
       Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
       k := params.AsInteger('max',100);
       k := params.AsInteger('max',100);
       l := params.AsInteger('start',0);
       l := params.AsInteger('start',0);
-      for j := 0 to Lanl.Count - 1 do begin
-        if (j>=l) then begin
-          account := FNode.GetMempoolAccount(Lanl.Get(j));
-          TPascalCoinJSONComp.FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+      LAccountsList := TList<Integer>.Create;
+      Try
+        Lanl.FillList(l,k,LAccountsList);
+        for j := 0 to LAccountsList.Count - 1 do begin
+          account := FNode.GetMempoolAccount(LAccountsList[j]);
         end;
         end;
-        if (k>0) And ((j+1)>=(k+l)) then break;
-      end;
+      Finally
+        LAccountsList.Free;
+      End;
       Result := true;
       Result := true;
     end else begin
     end else begin
       k := params.AsInteger('max',100);
       k := params.AsInteger('max',100);
@@ -2783,14 +2786,20 @@ begin
       c := 0;
       c := 0;
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
         Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
-        for j := 0 to Lanl.Count - 1 do begin
-          if (c>=l) then begin
-            account := FNode.GetMempoolAccount(Lanl.Get(j));
-            TPascalCoinJSONComp.FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+        LAccountsList := TList<Integer>.Create;
+        Try
+          Lanl.FillList(0,Lanl.Count,LAccountsList);
+          for j := 0 to LAccountsList.Count - 1 do begin
+            if (c>=l) then begin
+              account := FNode.GetMempoolAccount(LAccountsList[j]);
+              TPascalCoinJSONComp.FillAccountObject(account,jsonarr.GetAsObject(jsonarr.Count));
+            end;
+            inc(c);
+            if (k>0) And (c>=(k+l)) then break;
           end;
           end;
-          inc(c);
-          if (k>0) And (c>=(k+l)) then break;
-        end;
+        Finally
+          LAccountsList.Free;
+        End;
         if (k>0) And (c>=(k+l)) then break;
         if (k>0) And (c>=(k+l)) then break;
       end;
       end;
       Result := true;
       Result := true;
@@ -2846,9 +2855,17 @@ begin
       end;
       end;
       Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
       Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
       account.balance := 0;
       account.balance := 0;
-      for j := 0 to Lanl.Count - 1 do begin
-        inc(account.balance, FNode.GetMempoolAccount(Lanl.Get(j)).balance );
-      end;
+
+      LAccountsList := TList<Integer>.Create;
+      Try
+        Lanl.FillList(0,Lanl.Count,LAccountsList);
+        for j := 0 to LAccountsList.Count - 1 do begin
+          inc(account.balance, FNode.GetMempoolAccount(LAccountsList[j]).balance );
+        end;
+      Finally
+        LAccountsList.Free;
+      End;
+
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       Result := true;
       Result := true;
     end else begin
     end else begin
@@ -2857,9 +2874,17 @@ begin
       account.balance := 0;
       account.balance := 0;
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
       for i:=0 to _RPCServer.WalletKeys.AccountsKeyList.Count-1 do begin
         Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
         Lanl := _RPCServer.WalletKeys.AccountsKeyList.AccountKeyList[i];
-        for j := 0 to Lanl.Count - 1 do begin
-          inc(account.balance, FNode.GetMempoolAccount(Lanl.Get(j)).balance );
-        end;
+
+        LAccountsList := TList<Integer>.Create;
+        Try
+          Lanl.FillList(0,Lanl.Count,LAccountsList);
+          for j := 0 to LAccountsList.Count - 1 do begin
+            inc(account.balance, FNode.GetMempoolAccount(LAccountsList[j]).balance );
+          end;
+        Finally
+          LAccountsList.Free;
+        End;
+
       end;
       end;
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       jsonresponse.GetAsVariant('result').value := ToJSONCurrency(account.balance);
       Result := true;
       Result := true;

+ 35 - 32
src/gui-classic/UGridUtils.pas

@@ -289,66 +289,69 @@ uses
 
 
 procedure TAccountsGridUpdateThread.BCExecute;
 procedure TAccountsGridUpdateThread.BCExecute;
 Var
 Var
-  l : TAccountsNumbersList;
-  i,j, j_min, j_max : Integer;
+  LAccountsNumbersList : TAccountsNumbersList;
+  i,j, j_min : Integer;
   c  : Cardinal;
   c  : Cardinal;
   LApplyfilter : Boolean;
   LApplyfilter : Boolean;
   LAccount : TAccount;
   LAccount : TAccount;
   LNode : TNode;
   LNode : TNode;
+  LAccountsList : TList<Integer>;
 begin
 begin
   LApplyfilter := ((FAccountsGridFilter.MinBalance>0) Or ((FAccountsGridFilter.MaxBalance>=0) And (FAccountsGridFilter.MaxBalance<CT_MaxWalletAmount)));
   LApplyfilter := ((FAccountsGridFilter.MinBalance>0) Or ((FAccountsGridFilter.MaxBalance>=0) And (FAccountsGridFilter.MaxBalance<CT_MaxWalletAmount)));
   FBalance := 0;
   FBalance := 0;
   LNode := FAccountsGrid.Node;
   LNode := FAccountsGrid.Node;
   try
   try
-      if (Assigned(FAccountsGridFilter.OrderedAccountsKeyList)) then begin
-        if (FAccountsGridFilter.indexAccountsKeyList<0) then i := 0
-        else i := FAccountsGridFilter.indexAccountsKeyList;
+    if (Assigned(FAccountsGridFilter.OrderedAccountsKeyList)) then begin
+      if (FAccountsGridFilter.indexAccountsKeyList<0) then i := 0
+      else i := FAccountsGridFilter.indexAccountsKeyList;
 
 
-        while (Not Terminated) and (i<FAccountsGridFilter.OrderedAccountsKeyList.Count)
-          and ((FAccountsGridFilter.indexAccountsKeyList<0) or (FAccountsGridFilter.indexAccountsKeyList=i)) do begin
+      while (Not Terminated) and (i<FAccountsGridFilter.OrderedAccountsKeyList.Count)
+        and ((FAccountsGridFilter.indexAccountsKeyList<0) or (FAccountsGridFilter.indexAccountsKeyList=i)) do begin
 
 
-          j_min := 0;
+        j_min := 0;
 
 
           while (j_min>=0) do begin
           while (j_min>=0) do begin
 
 
           LNode.bank.SafeBox.StartThreadSafe;
           LNode.bank.SafeBox.StartThreadSafe;
           FAccountsGridFilter.OrderedAccountsKeyList.Lock; // Protection v4
           FAccountsGridFilter.OrderedAccountsKeyList.Lock; // Protection v4
           Try
           Try
-            l := FAccountsGridFilter.OrderedAccountsKeyList.AccountKeyList[i];
-            if Assigned(l) then begin
-
-              j_max := (j_min + 500);
-              if j_max>=l.Count then j_max := l.Count-1;
-
-              for j := j_min to j_max do begin
-                LAccount := LNode.Bank.SafeBox.Account(l.Get(j));
-                if LApplyfilter then begin
-                  if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
+            LAccountsNumbersList := FAccountsGridFilter.OrderedAccountsKeyList.AccountKeyList[i];
+            if Assigned(LAccountsNumbersList) then begin
+
+              LAccountsList := TList<Integer>.Create;
+              Try
+                LAccountsNumbersList.FillList(j_min,500,LAccountsList);
+                for j := 0 to LAccountsList.Count - 1 do begin
+                  LAccount := LNode.Bank.SafeBox.Account(LAccountsList[j]);
+
+                  if LApplyfilter then begin
+                    if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
+                      FProcessedList.Add(LAccount.account);
+                      FBalance := FBalance + LAccount.balance;
+                    end;
+                  end else begin
                     FProcessedList.Add(LAccount.account);
                     FProcessedList.Add(LAccount.account);
                     FBalance := FBalance + LAccount.balance;
                     FBalance := FBalance + LAccount.balance;
                   end;
                   end;
-                end else begin
-                  FProcessedList.Add(LAccount.account);
-                  FBalance := FBalance + LAccount.balance;
+                  if Terminated then Exit;
                 end;
                 end;
-                if Terminated then Exit;
-              end;
-              j_min := j_max+1;
-              if (j_max>=(l.Count-1)) then begin
-                j_min := -1;
-                break;
-              end;
+                if LAccountsList.Count>0 then inc(j_min,LAccountsList.Count)
+                else break;
+
+              Finally
+                LAccountsList.Free;
+              End;
+
             end;
             end;
           finally
           finally
             FAccountsGridFilter.OrderedAccountsKeyList.Unlock;
             FAccountsGridFilter.OrderedAccountsKeyList.Unlock;
             LNode.Bank.SafeBox.EndThreadSave;
             LNode.Bank.SafeBox.EndThreadSave;
           end;
           end;
-            if j_max>=0 then Sleep(0);
 
 
-          end;
-          inc(i);
         end;
         end;
-      end else begin
+        inc(i);
+      end;
+    end else begin
         c := 0;
         c := 0;
         while (c<LNode.Bank.SafeBox.AccountsCount) and (Not Terminated) do begin
         while (c<LNode.Bank.SafeBox.AccountsCount) and (Not Terminated) do begin
           LAccount := LNode.Bank.SafeBox.Account(c);
           LAccount := LNode.Bank.SafeBox.Account(c);