views:

552

answers:

4

Problem. I need a way to find Starteam server time through Starteam Java SDK 8.0. Version of server is 8.0.172 so method Server.getCurrentTime() is not available since it was added only in server version 9.0.

Motivation. My application needs to use views at specific dates. So if there's some difference in system time between client (where the app is running) and server then obtained views are not accurate. In the worst case the client's requested date is in the future for server so the operation results in exception.

A: 

<stab_in_the_dark> I'm not familiar with that SDK but from looking at the API if the server is in a known timezone why not create and an OLEDate object whose date is going to be the client's time rolled appropriately according to the server's timezone? </stab_in_the_dark>

Yiannis
That's not about timezones. System clocks of a server and a client in real world may not be synchronized and my app needs to calculate that time shift to operate correctly.
wheleph
+2  A: 

After some investigation I haven't found any cleaner solution than using a temporary item. My app requests the item's time of creation and compares it with local time. Here's the method I use to get server time:

public Date getCurrentServerTime() {
 Folder rootFolder = project.getDefaultView().getRootFolder();

 Topic newItem = (Topic) Item.createItem(project.getTypeNames().TOPIC, rootFolder);
 newItem.update();
 newItem.remove();
 newItem.update();
 return newItem.getCreatedTime().createDate();
}
wheleph
+1  A: 

If your StarTeam server is on a Windows box and your code will be executing on a Windows box, you could shell out and execute the NET time command to fetch the time on that machine and then compare it to the local time.

net time \\my_starteam_server_machine_name

which should return:

"Current time at \\my_starteam_server_machine_name is 10/28/2008 2:19 PM"

"The command completed successfully."
Dougman
Well, my StarTeam server is on Unix box. But even if it ran on Windows I wouldn't like tying to a particular platform. Anyway your answer gives another possible solution. Thanks.
wheleph
+1  A: 

We needed to come up with a way of finding the server time for use with CodeCollab. Here is a (longish) C# code sample of how to do it without creating a temporary file. Resolution is 1 second.

    static void Main(string[] args)
    {
        // ServerTime replacement for pre-2006 StarTeam servers.
        // Picks a date in the future.
        // Gets a view, sets the configuration to the date, and tries to get a property from the root folder.
        // If it cannot retrieve the property, the date is too far in the future.  Roll back the date to an earlier time.

        DateTime StartTime = DateTime.Now;

        Server s = new Server("serverAddress", 49201);
        s.LogOn("User", "Password");

        // Getting a view - doesn't matter which, as long as it is not deleted.
        Project p = s.Projects[0];
        View v = p.AccessibleViews[0]; // AccessibleViews saves checking permissions.

        // Timestep to use when searching.  One hour is fairly quick for resolution.
        TimeSpan deltaTime = new TimeSpan(1, 0, 0);
        deltaTime = new TimeSpan(24 * 365, 0, 0);

        // Invalid calls return faster - start a ways in the future.
        TimeSpan offset = new TimeSpan(24, 0, 0);

        // Times before the view was created are invalid.
        DateTime minTime = v.CreatedTime;
        DateTime localTime = DateTime.Now;

        if (localTime < minTime)
        {
            System.Console.WriteLine("Current time is older than view creation time: " + minTime);

            // If the dates are so dissimilar that the current date is before the creation date,
            // it is probably a good idea to use a bigger delta.
            deltaTime = new TimeSpan(24 * 365, 0, 0);

            // Set the offset to the minimum time and work up from there.
            offset = minTime - localTime;
        }

        // Storage for calculated date.
        DateTime testTime;

        // Larger divisors converge quicker, but might take longer depending on offset.
        const float stepDivisor = 10.0f;

        bool foundValid = false;

        while (true)
        {
            localTime = DateTime.Now;

            testTime = localTime.Add(offset);

            ViewConfiguration vc = ViewConfiguration.CreateFromTime(testTime);

            View tempView = new View(v, vc);

            System.Console.Write("Testing " + testTime + " (Offset " + (int)offset.TotalSeconds + ") (Delta " + deltaTime.TotalSeconds + "): ");

            // Unfortunately, there is no isValid operation.  Attempting to
            // read a property from an invalid date configuration will
            // throw an exception.
            // An alternate to this would be proferred.
            bool valid = true;
            try
            {
                string testname = tempView.RootFolder.Name;
            }
            catch (ServerException)
            {
                System.Console.WriteLine(" InValid");
                valid = false;
            }

            if (valid)
            {
                System.Console.WriteLine(" Valid");

                // If the last check was invalid, the current check is valid, and 
                // If the change is this small, the time is very close to the server time.
                if (foundValid == false && deltaTime.TotalSeconds <= 1)
                {
                    break;
                }

                foundValid = true;
                offset = offset.Add(deltaTime);
            }
            else
            {
                offset = offset.Subtract(deltaTime);

                // Once a valid time is found, start reducing the timestep.
                if (foundValid)
                {
                    foundValid = false;
                    deltaTime = new TimeSpan(0,0,Math.Max((int)(deltaTime.TotalSeconds / stepDivisor), 1));
                }
            }

        }

        System.Console.WriteLine("Run time: " + (DateTime.Now - StartTime).TotalSeconds + " seconds.");
        System.Console.WriteLine("The local time is " + localTime);
        System.Console.WriteLine("The server time is " + testTime);
        System.Console.WriteLine("The server time is offset from the local time by " + offset.TotalSeconds + " seconds.");
    }

Output:

Testing 4/9/2009 3:05:40 PM (Offset 86400) (Delta 31536000):  InValid
Testing 4/9/2008 3:05:40 PM (Offset -31449600) (Delta 31536000):  Valid
...
Testing 4/8/2009 10:05:41 PM (Offset 25200) (Delta 3):  InValid
Testing 4/8/2009 10:05:38 PM (Offset 25197) (Delta 1):  Valid
Run time: 9.0933426 seconds.
The local time is 4/8/2009 3:05:41 PM
The server time is 4/8/2009 10:05:38 PM
The server time is offset from the local time by 25197 seconds.
Jeremy Murray