Remote access to the Embarcadero License Center via SSH tunnel

 Delphi  Comments Off on Remote access to the Embarcadero License Center via SSH tunnel
Apr 282018
 

Once you have set up an Embarcadero License Center (ELC) for your company (with network named user or concurrent licenses) you will need network access to it in order to start the Delphi IDE.

Usually the server will only be accessible from within your intranet (I for one would not trust the ELC security to be good enough to let that server directly face the Internet.). So, in order to access it from a remote computer (e.g. your notebook on a customer’s site or your PC in your home office), that computer must have access to your intranet. If the connection is not available, Delphi will revert to offline usage which will work fine until the offline usage period expires which by default is 7 days but can be configured to up to 30 days.

There are multiple options to provide that access, the one I use is SSH tunneling via Putty.

By default the ELC listens on port 5567 for clients to connect to it, that port is specified when importing a license into ELC and cannot be changed later. The license manager reads the server name and port from the .slip file you provided to it, so you need a way to

  1. Resolve the name to the IP address
  2. Tunnel the port to your intranet

Let’s say, the name of your server is elc.yourcompany.local, its internal IP address is 192.168.1.200 and it listens on the default port 5567.

Name resolution can easily be done by adding an entry to the hosts file, but which IP do put there? If you add the IP of the actual server, it will not work, because that IP is in the intranet and your computer is not, so routing will fail. But using ssh you can tunnel local ports to remote ports, so we add our localhost IP (127.0.0.1) to the hosts file:

# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host
#
# localhost name resolution is handle within DNS itself.
#       127.0.0.1       localhost
#       ::1             localhost
127.0.0.1 elc.yourcompany.local

This will tell the client to expect the server to be listening on 127.0.0.1:5567. Now we only need to tunnel that local port to the actual ELC server by adding an entry to Putty:

Don’t forget to save that session configuration in order for it to be available later.

Now, simply connect your ssh session, start Delphi and voila, it will connect to the ELC, request a license and you are done.

TThread is not a normal class

 Delphi, GExperts  Comments Off on TThread is not a normal class
Apr 222018
 

In Delphi, threads have traditionally been implemented as classes descending from TThread. While there have been quite a few improvements to multithreading, TThread is still the most compatible way. But TThread is not a normal class.

In a normal class, the constructor and destructor usually look like this:

constructor TSomeClass.Create;
begin
  inherited;
  FSomeList := TStringList.Create;
end;

destructor TSomeClass.Destroy;
begin
  FreeAndNil(FSomeList);
  inherited;
end;

In the constructor, we first call inherited and afterwards add code to initialize additional fields of the object. In the destructor we first free any fields of the object and only then call inherited for the ancestor class to free its resources.

Now, TThread is peculiar because its constructor and destructor are usually executed in the program’s main thread, while its Execute method is executed in a different thread. But, when is that thread started? It’s started when you call the inherited constructor. So any initialization that thread needs must be done before calling inherited!

Edit: Several people have pointed out that my claim is somewhat “outdated”, where “outdated” means that since Delphi 6 the thread is started in the AfterConstruction method rather than in Create. In Delphi 5 it was the last command in TThread.Create (here is a probably not authorized copy of that code, search for “Delphi5Thread” on the page).

What I wrote about the destructor is still true though.

constructor TMyThread.Create;
begin
  FSomeList := TStringList.Create;
  inherited;
end;

Otherwise the field FSomeList might not have been initialized when the thread tries to access it.

Similar, if the thread is still running, you must be sure that all the resources it requires are available until it has stopped. So, the first thing would be to tell the thread to terminate, wait for it to actually do that and only then destroy it.

MyThread := TMyThread.Create;
// do something else while the thread does its thing
// ...
// now tell it to terminate (this is standard way of doing that
// but it might not be the best)
MyThread.Terminate;
// and destroy it
FreeAndNil(MyThread);

But that’s only half of it. The destructor must also take care not to destroy anything the thread still needs:

destructor TMyThread.Destroy;
begin
  // first, wait for the thread to terminate
  // (the inherited destructor calls WaitFor)
  inherited;
  // now the thread has definitely terminated, so we can free the resources
  FreeAndNil(FSomeList);
end;

Beware: These are just the simplest precautions to take when programming with multiple threads. As they say: "Creating threads is easy but multithreading is hard." If you can, use a library that does the ground work for you.

Why do I blog about this? I just fixed a few Access Violations in GExperts that were caused by TThread objects implemented the wrong way. (I have no idea who did that, it’s quite possible that I am myself to blame for that.)

If your Samba logon script does not get executed

 Linux  Comments Off on If your Samba logon script does not get executed
Apr 132018
 

… even though you can open and read it fine in an editor:

You should check its Linux access permissions. If it is not marked as executable, this might be the cause.

Change it with chmod like this:

root@server:/home/netlogon$ ls -la
total 12
drwxrwxr-x+  2 root root 4096 Apr 13 09:04 .
drwxr-xr-x  46 root root 4096 Mar  6 12:08 ..
-rw-rw-r--   1 root root 2535 Mar  6 14:32 logon.cmd
root@server:/home/netlogon$ chmod +x logon.cmd
root@server:/home/netlogon$ ls -la
total 12
drwxrwxr-x+  2 root root 4096 Apr 13 09:04 .
drwxr-xr-x  46 root root 4096 Mar  6 12:08 ..
-rwxrwxr-x   1 root root 2535 Mar  6 14:32 logon.cmd

The same goes for other executables on Samba shares.

In my case this was the last known problem left from a recent server migration. It worked before, didn’t work after. Something changed with the Samba configuration or maybe it was a change in Samba itself.

how to get a dump of your remote svn repository

 TortoiseSVN  Comments Off on how to get a dump of your remote svn repository
Apr 082018
 

Recently SourceForge’s service has declined to a point where it gets really annoying. Basically every time I tried to commit a change to the svn repository of one of my projects, I run into timeouts and other errors. I want to spend my time working on my projects, not convincing their infrastructure to accept my changes.

So I went looking for alternatives and discovered that basically every hosting service nowadays supports git, some add Mercurial and only very few also offer Subversion. Some claim to offer Subversion access to git repositories but whenever I actually tried that, it turned out that it either didn’t work at all or had limitations. Usually the limitation was that svn:external tags were not supported.

OK, this blog post was supposed to be about getting a dump of a remote svn repository, not about hosting services and their limitations…

The usual advice you find, when you google for “svn dump repository” is to use svnadmin. Unfortunately it turns out that svnadmin only works for local repositories so it is not suitable for dumping a repository on SourceForge. There are a few tools that claim to sync repositories but none of them worked for me. Eventually I found a reference to svnrdump, which is included in TortoisSVN and is exactly what I was looking for:

svnrdump dump http://svn.code.sf.net/p/dzlib/code > dzlib.svndump

creates a dump of the repository in the same format as svnadmin does. In theory it can also load that dump into a remote repository, but that requires that the target repository has been prepared for that operation.

Unfortunately, even that operation timed out just now why trying to download revision 162 (of 744), so I’m back to square one.

Edit: I eventually succeeded with the above command. But, as Ondrej Kelle pointed out in his comment on my Google+ post, for SourceForge there is a simpler and more robust way: Create a local copy of the repository.

rsync -a -v svn.code.sf.net::p/dzlib/code/ .

It’s even documented in the SourceForge support documentation (I only found it after I knew of this option). It requires the rsync tool, which is not available under Windows by default, but hey, are there any developers who don’t have access to a Linux computer or VM?

Once you have got that local copy, you can simply use svnadmin to create a dump from it:

svnadmin dump --incremental --deltas path\to\repository > repository.dump

I added the options –incremental and –deltas after initially loading the dump into a fresh repository failed when it encountered the first binary file. With these options, the problem did not occur.

svnadmin load --file repository.dump path\to\new\repository

Note: The following failed for me under Windows 8.1:

type repository.dump | svnadmin load path\to\new\repository