Jump to content

Larry Hengen

Members
  • Content Count

    87
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by Larry Hengen


  1. 7 hours ago, sakura said:

    Further information can be found in our official job offer: https://www.psyprax.de/wp-content/uploads/2023/Stellenanzeigen/MA_Software-Entwickler_.pdf

     

    Feel free to contact me for any questions.

    I see the job post is in German.  Do you have an English translation?  Is the position open to remote developers, or on-site?  If open to remote devs, what time zones will be considered?

    • Like 1

  2. I am attempting to get FastMM4 working in a legacy product that currently uses Delphi Berlin so the team can use Full Debug mode to eliminate existing leaks and prevent new ones.  The solution integrates .NET assemblies using ManagedVCL, and uses a combination of statically linked run-time packages and dynamically loaded packages with RTTI used to invoke methods.  Currently FastMM4 is the first unit in the main EXE's DPR, and when the application is terminated at the login form, FastMM reports huge leaks followed by an AV just as documented in the FastMM4 FAQ which indicates this is a DLL ordering issue.

     

    I am looking for some advice from anyone else with a similar experience on how they tracked down the offending DLL/BPLs and fixed the issues.  It takes quite some time for FastMM4 to report the leaks each run, and if I stop the process, the Berlin debugger becomes unstable after the 2nd or 3rd time. I've already fixed a circular BPL reference which according to Windows LoadLibrary can confuse things, but it didn't seem to resolve anything.  Most core third party components and a minimal set of BPLs are loaded at the login form, so I expect more issues will arise as I get into different areas of the application.

     

    I was thinking about using CodeSite to trace all the initialization/finalization sections, but the product uses a lot of third party components.  Looking for suggestions on how to approach this in a structured manner.


  3. I am using an old version of FireDAC (Berlin time frame) and when opening an updateable query it implicitly calls sp_pkeys which can take ~1.5s to return.  It seems to do so only once and then caches the PK info for the table appearing in the SQL FROM clause.  Grepping the source has yielded no information, and my Google fu is failing me. Depending on the use case, this sometimes results in poor performance.  For instance if the user fires up the app and goes into a screen to update some data and then closes the app, they trigger all of the metadata queries during their usage.  Over slower VPN connections this can be a real problem.  It would be nice to be able to prevent FireDAC from making such a metadata call.  Can we specify the PK column at design-time or run-time and prevent the metadata query?  After all the database PKs seldom change.


  4. Thanks all for the responses.  Turns out the AVs are due to the debugger in Berlin exploding when attempting to inspect the variables and not my actual code.  Injected CodeSite Messages to find out the actual values at run-time and validate the code was correct.


  5. I am using an ancient version (17.1.5) of the ExpressEditors and have a simple frame in which I am attempting to validate one editor based on the contents of two others.  From what I have found on-line and in the help it seems to me that accessing the EditValue of a TcxCustomEdit descendant should be fine at run-time, but I get an AV or other error in the debugger (Berlin) and the application does not behave correctly.  i have explored all other public properties as well, and none seem appropriate.  Anyone know the cause without tracing through all the DevExpress code?  In the TFrameDailyHours.editHoursPropertiesValidate method I am attempting to make sure the Hours edit does not contain a value that exceeds the difference of the two other time edit controls:

     

    unit UnitFrameDailyHours;

    interface

    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
      Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters,
      cxContainer, cxEdit, cxSpinEdit, cxTextEdit, cxMaskEdit, cxTimeEdit, Vcl.StdCtrls, Vcl.ExtCtrls;

    type
      TFrameDailyHours = class(TFrame)
        PanelDay7: TPanel;
        labelDayofWeek: TStaticText;
        CheckBoxOvernight: TCheckBox;
        TimeEditStart: TcxTimeEdit;
        TimeEditStop: TcxTimeEdit;
        editHours: TcxSpinEdit;
        procedure TimeEditStartPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
          var Error: Boolean);
        procedure TimeEditStopPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
          var Error: Boolean);
        procedure editHoursPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
          var Error: Boolean);
      public
      end;

    implementation

    {$R *.dfm}

    procedure TFrameDailyHours.TimeEditStartPropertiesValidate(Sender: TObject; var DisplayValue: Variant;
      var ErrorText: TCaption; var Error: Boolean);
    begin
      ErrorText := '';

      //Start Date is a required field
      Error := VarIsNull(DisplayValue);
      if Error then
        ErrorText := 'Start of Time Range cannot be Empty';
      Exit;

      //if we have a StopTime then the StartTime must be < StopTime
      Error := (DisplayValue >= TimeEditStop.EditValue);
      if Error then
        ErrorText := 'Start of Time Range must precede End of Time Range';
    end;

    procedure TFrameDailyHours.TimeEditStopPropertiesValidate(Sender: TObject; var DisplayValue: Variant;
      var ErrorText: TCaption; var Error: Boolean);
    begin
      ErrorText := '';
      if not (DisplayValue = EmptyStr) then
      begin
        Error := (DisplayValue < TimeEditStart.EditValue);
        if Error then
          ErrorText := 'End of Time Range must be Empty or after Start of Time Range';
      end;
    end;

    procedure TFrameDailyHours.editHoursPropertiesValidate(Sender: TObject; var DisplayValue: Variant;
      var ErrorText: TCaption; var Error: Boolean);
    begin
      ErrorText := '';
      Error := False;

      if not (TimeEditStart.DisplayValue = '00:00:00') and not (TimeEditStop.DisplayValue = '00:00:00') then
      begin
        Error := VarIsNull(DisplayValue);
        if Error then
        begin
          ErrorText := 'Hours cannot be Empty';
          Exit;
        end;

        Error := (DisplayValue < 0) or (DisplayValue > 24);
        if Error then
        begin
          ErrorText := 'Hours must be > 0 and < 24';
          Exit;
        end;

        //check that Hours does not exceed duration between Start and Stop Times
        if TimeEditStop.EditValue > TimeEditStart.EditValue then
        begin
          Error := (TimeEditStop.EditValue - TimeEditStart.EditValue) * 24 < DisplayValue;
          if Error then
          begin
            ErrorText := 'Hours exceeds duration between Start and End Times';
            Exit;
          end;
        end;
      end;
    end;

    end.


  6. Thanks for the suggestions.  I changed all the packages to Explicit ReBuild, not that it was the cause, but a good change anyway.

     

    Turns out I isolated the issue to the IDE injecting the FireDAC.FMXUI.Wait unit into the Interface section every time the unit was saved/compiled despite the fact it was already present, just wrapped in an IFDEF.  Took me a while to find out why it was adding the unit.  Turns out I had dropped a TFDGUIxWaitCursor component on the data module at some point.  Creating that component in code with the Provider set appropriately fixed the issue.  The dialog is obviously misleading as it has nothing to do with what packages are installed in the IDE.

    • Thanks 2

  7. I have a DataAcess package which is UI framework neutral and uses FireDAC.  When I build the package it prompts me to add FMX in order to be compatible with other installed packages. The interesting thing is that it is a RunTime Only Package with Rebuild as Needed.  There is only one package in the project group that is a design-time package and it does not require the DataAccess package.  If I cancel the IDE dialog, everything works as expected, but it's very annoying and I would like to understand the root cause. 

    I have a couple of defines {$IFDEF FMX} FireDAC.FMXUI.Wait, {$endif} that might be factors except that FMX is not defined.

     

    The package is a single datamodule unit. with an interface uses as follows:

     

    uses
      System.SysUtils, System.Classes, hcSQLMapper, hcTransactMgrIntf, hcComponent,
      hcFactoryPool, Data.DB, hcObject, hcPrimaryKeyConstraint,
      FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf,
      FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
      FireDAC.Phys, FireDAC.Phys.FB, FireDAC.Phys.FBDef,
      FireDAC.Comp.Client, hcFireDAC, FireDAC.Phys.IBBase, FireDAC.DApt, FireDAC.Comp.ScriptCommands,
      FireDAC.Stan.Util, hcLookupList, {$IFDEF FMX} FireDAC.FMXUI.Wait, {$endif}FireDAC.Comp.UI,
      FireDAC.Phys.IBDef, FireDAC.Phys.IB, FireDAC.FMXUI.Wait;

     

    and an implementation uses as follows:

     

    {$IFDEF FMX}
    {%CLASSGROUP 'FMX.Controls.TControl'}
    {$ENDIF}

    {$R *.dfm}

    uses
      hcQueryIntf, {$IFNDEF FMX} Vcl.Forms, VCL.Dialogs {$ELSE} FMX.DialogService, FMX.Forms, FMX.Dialogs {$ENDIF}, System.UITypes, FireDAC.Comp.Script;

     

    The message content in the dialog is as follows:

     

    Add fmx.
    fmx contains implicit unit(s) FMX.Printer.Win, FMX.Consts, FMX.Graphics, FMX.Utils, FMX.Types, FMX.Styles, FMX.Forms, FMX.AcceleratorKey, FMX.StdActns, FMX.VirtualKeyboard, FMX.Controls, FMX.Menus, FMX.MultiResBitmap, FMX.Platform, FMX.Clipboard, FMX.Clipboard.Win, FMX.Helpers.Win, FMX.Surfaces, FMX.ImgList, FMX.ActnList, FMX.Platform.Common, FMX.BehaviorManager, FMX.Platform.Win, FMX.Forms.Border, FMX.Controls.Presentation, FMX.Presentation.Win, FMX.ZOrder, FMX.ZOrder.Win, FMX.Presentation.Messages, FMX.Controls.Model, FMX.Controls.Win, FMX.Presentation.Win.Style, FMX.Presentation.Factory, FMX.Presentation.Style.Common, FMX.Ani, FMX.Presentation.Style, FMX.TextLayout, FMX.Text, FMX.Effects, FMX.Filter.Custom, FMX.Types3D, FMX.Materials, FMX.Filter, FMX.StdCtrls, FMX.Switch.Win, FMX.Styles.Switch, FMX.Styles.Objects, FMX.Objects, FMX.FontGlyphs, FMX.FontGlyphs.Win, FMX.Switch.Style, FMX.Dialogs, FMX.DialogService.Sync, FMX.MultiTouch, FMX.AcceleratorKey.Win, FMX.KeyMapping, FMX.WebBrowser, FMX.WebBrowser.Win, FMX.Controls.Ole, FMX.MultiTouch.Win, FMX.Gestures.Win, FMX.Gestures, FMX.DialogService, FMX.Forms.Border.Win, FMX.Edit, FMX.Edit.Win, FMX.Edit.Style, FMX.SpellChecker, FMX.MagnifierGlass, FMX.Layouts, FMX.InertialMovement, FMX.ExtCtrls, FMX.Pickers, FMX.Pickers.Default, FMX.Calendar, FMX.Calendar.Style, FMX.ListBox, FMX.ListBox.Selection, FMX.DateTimeCtrls, FMX.DateTimeCtrls.Types, FMX.Canvas.GPU, FMX.StrokeBuilder, FMX.Canvas.GPU.Helpers, FMX.Materials.Canvas, FMX.TextLayout.GPU, FMX.Context.DX11, FMX.Context.DX9, FMX.Canvas.D2D, FMX.Canvas.GDIP, FMX.Printer, FMX.Dialogs.Win, FMX.DialogHelper, FMX.Dialogs.Default, FMX.Header.

     

    Add fmxFireDAC.
    fmxFireDAC contains implicit unit(s) FireDAC.FMXUI.Wait.

     

    Is the IDE missing the fact that FMX is not defined, or what am I missing?

    Change to DataAcess - Adding FMX.png


  8. @Hans J. Ellingsgaard  I am using SQL Server.  The query uses an inner join on about 5 tables, a left outer on one and a cross apply with a group by and order by on the results  Pretty much a worst case scenario.  Some of the criteria is not indexed, and due to the data layout requires a large # of reads.  Some work has been done on the query to optimize it, and it's now better, but the question remains; what are the best settings to use for FireDAC when the cost and row count of a particular query is not generally known at design-time, as is the case with many dynamically built SQL queries.


  9. 4 hours ago, Hans J. Ellingsgaard said:

    To fetch all the records from a table to get the record count is in most cases a bad praxis. If it's a table with a lot of records, you will just put a lot unnessisary strain on the database server. A count(*) query, on the other hand,  has a very limited impact on the server. 

     

    I beg to differ.  The situation I encountered was that a very expensive SQL Server query wrapped in a select count(*) from() was causing major performance issues.  Result set was about 1500 rows.  In this case I think it's far easier to bring back the entire result set.  What I was looking for was guidelines other devs are using to make such decisions since the actual row counts are not well known.


  10. 1 minute ago, Hans J. Ellingsgaard said:

    You can use an extra query with a count(*) to get the number of records.

    That is exactly what FireDAC does for you so why would I write additional code to do the same thing?  I want to avoid a second query because it can be detrimental to your SQL back end's performance. Imagine doubling it's workload for every user...

     

    A less intensive approach is to fetch all records, but that can cause a delay in processing while they are streamed to the client, and if the query is in the main thread, the application will "freeze".

     


  11. I have recently encountered a situation where code was explicitly setting queries to use FetchOptions.RecordCountMode := cmTotal.  The query involved was rather complex and therefore expensive to execute and due to the RecordCountMode set, was being executed twice as per the FireDAC Documentation.  As a result, together with all the other workload it was bringing SQL Server to it's knees.  That got me thinking about what are appropriate (read least resource utilization with best performance) settings to use in the following scenarios:

     

    1) You open a query to gather data and iterate over each record not updating the record itself but perhaps issuing other SQL Statements., or generating a report

    -such a query could be ReadOnly, ForwardOnly

     

    2) You open a query with RequestLive = True and iterate over it updating values which FireDAC posts back to the database

     

    In both of the scenarios above, to display progress information you want the total record count.

     

    What do developers usually use for FireDAcC FetchMode/RecordCountMode and other settings in such scenarios and what if any combination of settings are done globally with a TFDManager vs. locally at the query level?

     


  12. @Lars Fosdal

    I did try to change the database file permissions but the exception remains.  The interesting thing is that I discovered the exception is not fatal.  I previously assumed that once it was thrown the application could not continue.  This is not the case.  The application opens and does appear to behave normally.  I can set a break point and debug the app, so the issue is not critical, but I would like to understand why an exception is thrown and resolve it.  I have attached the DB permissions both before and after changing them.

     

    I noticed a status error opening the DB through isql about access to /tmp/Firebird so I changed the permissions on that folder.  Now the exception is fatal :-).

     

    My conclusion is that I will have to post the exception on the Firebird forums for a developer to comment, or create a bug report if that doesn't work.  Seems to be an installation issue of some sort.  Thanks fro all the feedback.

    Db Permissions After.png

    Database Permissions.png


  13.  

    8 hours ago, Fr0sT.Brutal said:

    +1. Just copy DB file to another location. Do you really need connecting to DB locally? 

    It's not that simple.  I copied the DB to /home/larryh/Downloads/LinuxDBForCompositeTesting/COMPOSITEAPP.FDB but I get an exception (shown below) when FireDAC attempts to open the database when I am debugging.  As I said, I can run the app fine from the command line, but that doesn't help me debug the app on Linux.  The DB is owned by the Firebird Administrator.  I have tried changing ownership to my account but that doesn't resolve the error.


    Project FmxTaskApp raised exception class N8Firebird16status_exceptionE with message 'Exception Object Address: 0x1C04280'.

     

     

     

     

     

    Screenshot from 2020-09-08 11-08-47.png


  14. I experimented this weekend with deploying a small FMX app that uses a Firebird 3 database running on a Linux instance.  From reading the DockWiki it doesn't seem to me that you can deploy a database file on Linux (through a VM shared drive mapping), and if you copy the database file on the linux side to the scratch folder, it is removed once you attempt to debug the application over PAServer.

     

    Is there a way to prevent PAServer from deleting files that are not part of the deployment but appear in the scratch-dir?

     

    For some reason I also cannot debug the application, I get an N8Firebird16status_exceptionE exception when attempting to open the database connection.  The database file is present as I create it before the application attempts to open it.  I can however, run the application from the terminal window.  I assume it has something to do with permissions.  PAServer is running under my user account and FireDAC is establishing a local connection to the database which is in the same folder as the app.  It doesn't help using sudo to run PAServer, so I am at a loss...

     


  15. 44 minutes ago, Anders Melander said:

    I would think that the compiler would do that for you - i.e. give you a compile or linker error.

    I must admit that my experience with run-time packages are a couple of decades old but AFAIR the dcu files of the packages are stored in a dcp file. If the linker uses the dcp file instead of the dcu files then a interface change should result in a linker error - but I might of course be remembering this completely wrong.

     

    Since run-time packages are just statically linked DLLs I believe you just need to determine if all DLL dependencies can be resolved. It would be trivial to create a small utility that loaded you application with LoadLibraryEx  and have that do it, but unfortunately LoadLibraryEx only resolves dependencies when you load DLLs.

     

    Try Dependency Walker instead. It has a command line mode that you can probably use. I don't know what the output looks like though.

     

    Get rid of them (the packages, not the apps). 

    Thanks for the response and pointing me to Dependency Walker.

     

    As for the run-time packages, it's not my choice.  I was asking about best practices because I have normally been using Monolithic EXEs.  Didn't realize I was already using the best practices for package based apps ;-0


  16. If you have an application that uses run-time packages and are supporting an older release, you cannot change the interface of any package or you have to re-distribute all dependent packages instead just the one you're updating.  Is there anyway to detect interface breaking changes automatically (that it could be put on a build server)?  Any advice on maintaining apps using run-time packages?


  17. It uses a the same authentication as edn.embarcadero.com which gives an error.  Looks like the Oracle database is down or inaccessible:

     

    System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Data.OracleClient.OracleException: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor at System.Data.OracleClient.OracleException.Check(OciErrorHandle errorHandle, Int32 rc) at System.Data.OracleClient.OracleInternalConnection.OpenOnLocalTransaction(String userName, String password, String serverName, Boolean integratedSecurity, Boolean unicode, Boolean omitOracleConnectionName) at System.Data.OracleClient.OracleInternalConnection..ctor(OracleConnectionString connectionOptions) at System.Data.OracleClient.OracleConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject) at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.OracleClient.OracleConnection.Open() at EDN.Data.DbUtils.CreateConnection(ConnectionStringSettings ASettings, Boolean AOpen) at EDN.Data.DbUtils.CreateConnectionName(String AName) at MembershipWS.CDNMemberService.get_LookupSvc() at MembershipWS.CDNMemberService.GetCountryStatus(String CountryCode) --- End of inner exception stack trace

    I let Jim McKeeth know.  Hopefully that will spur resolution.


  18. 11 hours ago, sh17 said:

    Thanks for the links.  From what I understand the TMS Cloudpack has a Synchronization component which I will have to investigate.  As for Sabre, I ran into that in my google searches but I didn't think it would work for me as it's not a Delphi solution.  Will look into it's plugins further...thanks all for your suggestions.


  19. On 4/27/2020 at 8:05 AM, Bill Meyer said:

    ... the price is low. http://www.prodelphi.de/

     

    I agree the price is quite reasonable.  Not crazy about the UI, but it's usable.  I have been trying to use the ProDelphi 64 bit profiler against a large project using many run-time packages that has lots of code in the DPR. I am not getting the body code profiled.  Any tips?  I am trying to profile performance from startup to the appearance of the main form including any calls into the run-time packages.


  20. I was looking at the MS SQL sample project demonstrating FireDAC support for change notifications.  Has anyone used this to refresh data-aware lookup combo boxes?

     

    What is the real world database overhead?  How does it compare to polling?

     

    The sample project works fine, but I've noticed that if you launch multiple instances with a unique subscription name, only one gets notified of a change made in SSMS.  Any idea why? 

     

    I was hoping to use the sample app as a POC to help determine SQL Server overhead, and prove that all connected applications will receive change notifications.  I am using Berlin 10.2 and the only bug reports seem to be for Rio.

     

     

    • Like 1
×