Saturday, December 19, 2009

Project Update: One year on

Around one year ago, I was working very hard on some unpleasant projects at work at what seemed like a dead-end position in terms of where I wanted to be in my career. One aspect of this was that I wanted to be hard-core developer where as my current position was more consulting-oriented for a particular vendor.

Not being in a development position for about 3 years prior, I wanted to try to get some development experience under my belt in order to help landing a job in the field I wanted to be in. Given that I was not getting this opportunity at my job, I felt contributing to an Open Source project would be personally gratifying and giving me the chance to get deep into the code of an application and prove myself.

I made it a goal of 2009 to contribute to an open source project. This was my intention.

I focused on World Wind, given my enthusiasm for NASA, space travel, and geography. It was C#.NET which was a language I hadn't used in years and seemed interesting enough.

I found the code difficult, it took a long time for me to make any contributions, at first this was because of lack of documentation, but also lack of clear process or community support. No fault of anyone on the WorldWind project but it seemed to continually lose support, members and momentum throughout my involvement in 2009. What I didn't realize when I started is that although WorldWind has the NASA name, NASA has officially moved all their support to the Java WorldWind SDK project and virtually abandoned the .NET version. Not only does this mean that their full time developers who originally wrote WW.NET no longer made any contributions, they also removed the JIRA defect tracking site for the .NET project. This makes it impossible to track our progress, or even determine the goals of what needs to be fixed. I even got frustrated with this so I created a "bug tracking" page on the World Wind wiki just so we had something tangible to work against.

So after a year spent part-time on this OpenSource effort, I have made a number of contributions, the largest being perhaps the download code refactoring. I've also contributed to the project management side by documenting issues and pushing along input and contribution from the team members still active. I regret not being able to get into developing new features rather than just bug fixing, but in the Fall of 2009 my real-world job took precedence as I was assigned a literal Death March project.

As things stand we have a stable build with a number of fixes implemented. We have been discussing making a release of this build as World Wind 1.4.1, but as of this week I am still unclear on what steps are done to build and package this release. I gather it involves updating the installer and getting NASA to do some testing to sign-off on the changes. At the very least we have been giving people guidance on how to build their own WW app from the latest source with our changes. I suppose my efforts will live on.

In 2010 I am considering embarking on a personal web-site project. This will probably take most of my time outside of work, but I am very excited about this effort as I have control over it and can make a difference. Contributing to World Wind was an good experience but I feel it is time to move in a different direction, at least for the time being.

How does Visual Studio include Referenced Libraries?

A problem was raised on the forums a number of times about World Wind building in Release mode.

If you checked out the source from SVN, and opened the project in Visual Studio, then tried to build in release mode you would receive errors such as:


C:\WINDOWS\Microsoft.NET\Framework\v2.0. 50727\Microsoft.Common.targets : warning MSB3245: Could not resolve this reference. Could not locate the assembly "Tao.OpenGl.Glu". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.

C:\WINDOWS\Microsoft.NET\Framework\v2.0. 50727\Microsoft.Common.targets : warning MSB3245: Could not resolve this reference. Could not locate the assembly "ICSharpCode.SharpZipLib". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.

C:\WINDOWS\Microsoft.NET\Framework\v2.0. 50727\Microsoft.Common.targets : warning MSB3245: Could not resolve this reference. Could not locate the assembly "Tao.OpenGl.ExtensionLoader". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.

C:\Apache2\htdocs\html\WWsrc\PluginSDK\T iledWFSPlacenameSet.cs(10,7): error CS0246: The type or namespace name 'ICSharpCode' could not be found (are you missing a using directive or an assembly reference?)


Answer given by forum member, James_in_Utah:

I think the problem is that those DLLs may not be checked in for the "Release" mode build. Try building in Debug mode. That should work. Then find the dlls mentioned, Tao.OpenGl.Glu.dll, ICSharpCode.SharpZipLib.dll in the Debug target directory and just copy them to the Release mode target directory. We really probably should check these into the release mode build target directory in SVN, but I don't have privs to do that.


I added these two .dlls to the Release folder in World Wind SVN and commited the changes.

This brought the question to my mind, this seems to be a bad practice to check in to source control the contents of the output directory. I see that the .dlls are referenced under project references. Shouldn't there be a way that on build it copies the required .dlls to the Release folder or Debug folder as necessary?.

Unfortunately no one on the forum seemed to have a response and a quick web search revealed no answers.

Friday, September 18, 2009

Stars3d fix

I commited my changes to the Stars3d plugin. This was Issue #4. After a few days this was registered by ohloh as my 3rd commit. Also after some time my kudos rank registered this work and bumped me up to level 4. Hooray (sarcasm).

Right now the dev forums for World Wind are like a ghost town, I've replied several times and not heard anything back, no one else is currently working on fixes, and the one guy who was, has not checked in his changes to the trunk.

Since I am so busy with work, I can't do more, would like to keep this momentum going forward and maybe pick up some interest.

I went to Amsterdam two weeks ago for work. Next week I will be in London for two weeks for the same. Doesn't look like I will work on this anytime soon.

Monday, September 7, 2009

ohloh kudos

It seems that when I made commits for the two fixes that ohloh did get updated and track my commits to SVN which is good. But although I have an account there with a username which is the same as my SVN login "ammianus" it didn't associate that those commits were made by the me who had set up the ohloh "ammianus" account.

I guess it makes sense, since these are external systems, how can ohloh assume that just because someone made a commit to some repository and they happen to have the same screen name that they are the same person. I guess it makes sense so people can't accidentally take credit for other's work, although it seems there is nothing preventing someone from maliciously doing so.

While my starting "Kudos" rank was 1 (lowest), it looked like the "ammianus" who was logged as making commits to WorldWind had a level 4 Kudos rank. I thought that was cool. But when I associated my ohloh account to those commits, my rank went back down to 1. I wonder if the system takes some time to update? We'll wait and see for the gadget on the right to update.

Meanwhile, while I was traveling last few weeks on business and generally busy with work, seems that all momentum on the WW.NET seems to have petered out. I'll try to kick start things, I have one more bug fix to commit up my sleeve.

Sunday, August 23, 2009

Still working on issues

I am still working on the issues for World Wind 1.4.1. There hasn't been a lot of traction but at least one other dev was using my custom wiki bug tracker.

I did check in my Download code and Atmosphere plug-in fixes into the main trunk of World Wind code.

Now, I will start watching the WW project on ohloh for updates. Since I checked in to sourceforge svn using my ammianus id, my ohloh profile should reflect these commits to the WW project. Since it is my first check-in to trunk I don't know if it will work. They seem to refresh their statistics from SVN every 2 days or so.

Sunday, August 2, 2009

Fire up the bug tracker

I feel like I have had a pretty productive weekend in terms of WorldWind accomplishments. This entry is actually on time and not stale at the time of writing which is also a good sign.

First of all I finally got my act together and created a complete bug tracking wiki-article on the World Wind site. This page has a table containing general information and priority to bugs, then for each bug I created a section in the bottom half of the page for more detailed description and comments. It probably took me an hour or two to develop this, it's not secure and has a lot of manual editing to update anything, but its something. Its the first time I've been on this project we have been able concretely state what we know needs to get done and to say who is doing what. I have not gotten a whole lot of response, but so far one other active developer has stepped up and begun fixing items from that list. I've picked up another item as well.

Setting up that page was one thing, the second task was to populate it with data. I spent most of this morning reading and replying to threads in the WW Bug Reports Forum. From this I tried to glean the data to see what issues had been found by users but never addressed. The sad thing was a number of threads more than a year old with no replies where I could see no fix was ever made. Ok, I've been at it for 6 months and have not fixed many bugs myself, so I can understand it. I don't like it too much though.

Maybe I enjoy "process", but I feel I am not alone when finding things like proper defect tracking help software development rather than are a burden. I have taken the initiative to provide this data and calling it out. I am not quite sure what the reaction will be from more senior developers, hopefully there will be more positive responses so I will continue.


On the front of fixing bugs, I took a look at two Issues I came across with "Plug-in" code. The first I looked at was the "Starfield" plugin. The issue with this plugin is that it loads by default on start up. However, if you try to uncheck it from the Layer Manager, it will not unload the visible background stars. I would like to go into the Plug-in architecture more later. But basically there is a single Stars3d.cs file containing the Plugin code plus some initialization and data files that get stored in a Plug-ins directory in the application folder. After some trial and error I got this to work by a simple line change in the Stars3DLayer class's Render(DrawArgs) method, approx inserted after line 151

if (!this.IsOn)
return;

IsOn is an inherited property of the RenderableObject base class for the layer. It gets set true or false by the LayerManager when the check/uncheck happens, there seems to be no other hook to the plugin itself when that event is handled in the LayerManager UI.

I made a further enhancement so that the SaveSettings(),ReadSettings(),Dispose() methods would actually save the sate of that check, either On or Off so that if you check it off, the next time you start WorldWind it will stay off (but still loaded).

Open Questions: I'm not sure if there is a some other way that the WW is supposed to know not to render a layer if IsOn == false?
Is there a "business" reason why they wouldn't want the plugin's last state (checked or unchecked) to be persistent?


The second issue I stumbled upon when trying to understand how the LayerManager worked by looking at other plugin code. I tried one called Atmosphere.cs which didn't seem to do anything but repeatedly cause System.NullReferenceException. I traced through this and found a fix pretty quickly. A summary of what I found and my fix can be found in this Bug Report thread


PS: Thanks to The Wandering Geek Blog for the tip on how to configure the blogger styles to render the code blocks nicely with a background. e.g.(Atmosphere.cs):
// Set new one (to avoid being clipped) - probably better ways of doing this?
float aspectRatio = (float)device.Viewport.Width / device.Viewport.Height;
device.Transform.Projection = Matrix.PerspectiveFovRH((float)camera.Fov.Radians, aspectRatio, 1, (float)(2*world.EquatorialRadius) );
device.TextureState[0].ColorOperation = TextureOperation.BlendCurrentAlpha;

Download Code checked in

This is also a few weeks late, I finished testing on the last weeks of my vacation in mid-July while still in Korea. The folks at WorldWindCentral were kind enough to provide me commit access to SVN, so I have started my own branch to check in the changes. So far this has not been commited to /trunk yet.

Here is the the URL for my shiny new SVN branch:
https://nasa-exp.svn.sourceforge.net/svnroot/nasa-exp/branches/ammianus

As far as the Download code I also I posted a detail list of the fixes I have done here:
http://worldwindcentral.com/wiki/1_4_1_Issues#Download_code_error_response_handling

Logical changes include new error response handling:
* 4xx / Client error are cached as failures and WW will not retry to download them during that session (cache is in memory only and cleared when WW is exited).

  • 400 Bad Request

  • 401 Unauthorized

  • 403 Forbidden

  • 404 Not Found

  • 206 Partial Content

  • 200 OK && Content length == 0


* 5xx / Server Error are recorded and a timeout period will begin before requests are allowed to this server again. A message is displayed in the top right of the UI stating the timeout length. If server response contains "retry-after" header, that period is used, otherwise default is 2 minutes.

  • 500 Internal Server Error

  • 501 Not Implemented

  • 502 Bad Gateway

  • 503 Service Unavailable


Changes made to source files:

* WebDownload/WebDownload.cs
* PluginSDK/QuadTileSet.cs
* PluginSDK/Renderable/GeoSpatialDownloadRequest.cs

Sunday, July 26, 2009

Creating Local Tile Servlet

I meant to write my updates when I got back from my trip a week ago, but there are a lot of things at home to take care of after a three week vacation. As promised I did some work on the WorldWind while I was away.

Creating Local Tile Server
With an unsteady internet connection I needed to be able to continue to test WorldWind changes that related to the download code. If I could set up a local server, and point my WorldWind program to check that for tiles I could still check the download code if it works. A side benefit is that in theory if my local tile server is something I coded myself, I'd be able to insert dummy error response codes like 404 or 500 errors in order to test the behavior for those errors in the new download code.

I tried using existing scripts and code that was posted on the WorldWindCentral wiki. But I either don't have the right application server software to run them (PHP, Perl,Python) or the know-how to set it up and use it (IIS 7/aspx.cs). There is also a WorldWind server, written in java posted on the World Wind forums (NASA World Wind WMS Server Config), I tried that too, this would allow me to set up a local server but because it was a self-contained application, but wouldn't let me achieve my second goal of inserting my own custom errors for testing. Even so, it has dependencies on all or some of WorldWind Java SDK. Now on my own, but understanding better what needs to get done, I thought "Why not just write this in a language I know, Java and set up Tomcat with a simple web app?"

Taking the .aspx.cs example, I ported that to a Java Servlet class.

package org.wwc.ammianus.tomcat.tileserver;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
*

This servlet handles requests from the World Wind.NET application and returns
* tile images or error codes as appropriate. This was a port to Java of a ASP.NET file posted
* at http://worldwindcentral.com/wiki/Data_serving_scripts


*
* @author ammianus
* @version 0.1
*
*
*/
public class TileRequestHandler extends HttpServlet {

/**
* Generated by Eclipse
*/
private static final long serialVersionUID = -6596187549520730077L;
/**
* settings Map which theoretically could be extended for any layer used in WW
* for each layer, use the <DataSetName></DataSetName> tag value from @Images.xml file
* create three map entries <DataSetName>, <DataSetName>_EXT, <DataSetName>_MIME
*/
private HashMap _settings;

private int _requestNumber;

/**
* @see HttpServlet#HttpServlet()
*/
public TileRequestHandler() {
super();
//use these setting which theoretically could be extended for any layer used in WW
//for each layer, use the tag value from @Images.xml file
//create three map entries , _EXT, _MIME
_settings = new HashMap();
_settings.put("geocover2000", "C:\\Users\\Public\\WorldWindCache\\Cache\\Earth\\Images\\NASA Landsat Imagery\\Geocover 2000");
_settings.put("geocover2000_EXT", ".jpg");
_settings.put("geocover2000_MIME", "image/jpeg");

_requestNumber = 0;
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//increment counter
_requestNumber++;

//Un-comment this to test whether WW handles 503 return code with Retry-After header
//
//first request we will send an error with a retry-after header
//
/*if(_requestNumber == 1){
response.setStatus(503);
//this appears to be case insensitive for WorldWind, I just picked a random retry-after period
response.setHeader("retry-after", "38");
System.out.println(_requestNumber+":Response: 503, with retry-after: 38");
return;
}*/

try{


//column
int X = Integer.parseInt(request.getParameter("X").toString());
//row
int Y = Integer.parseInt(request.getParameter("Y").toString());
//level
int L = Integer.parseInt(request.getParameter("L").toString());
//DataSet name
String T = request.getParameter("T").toString(); //T = Dataset in WorldWind parlance


//Un-comment this to test whether WW handles 500 return code
//
//if(T.equals("geocover2000")){
// throw new Exception("Force return of 500 - Server Error");
//}

//Arguments are in this format URL sent from world wind
//e.g. http://localhost:8080/TomcatTileServer/TileRequestHandler?T=geocover2000&L=0&X=47&Y=21
String filePath = _settings.get(T);//WebConfigurationManager.AppSettings[T];

String fileExt = _settings.get(T + "_EXT");
if(L < 3){
DecimalFormat df = new DecimalFormat("0000");
filePath += "\\"+L + "\\" + df.format(Y) + "\\" + df.format(Y) + "_" + df.format(X) + fileExt;
}else{
filePath += "\\level"+(L+1)+fileExt;
}
//request.get
System.out.println(_requestNumber+":Requested File: "+filePath);
File file = new File(filePath);

//if file (image for requested tile) is not found on server, return 404
if (!file.exists())
{
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Not Found");
}
else
{
//set content length to file size
response.setContentLength((int) file.length());
//get mime type for this layer
response.setContentType(_settings.get(T + "_MIME"));
//get the output stream for the response, this will have the file written to it
ServletOutputStream stream = response.getOutputStream();

//read the file contents and write them to the outputstream
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[1024];
int counter = 0;
while(counter < file.length()){
fis.read(bytes);
counter += 1024;
stream.write(bytes);
}
fis.close();
stream.flush();
stream.close();

//done with response
}
}catch(Exception e){
//uncaught Exception return 500 error
response.sendError(500,e.getMessage());
System.out.println(_requestNumber+":Response: send 500 error");
}

}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}

}

As you can see, not much there. In my WEB-INF/web.xml, I included the new servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>TomcatTileServer</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>TileRequestHandler</display-name>
<servlet-name>TileRequestHandler</servlet-name>
<servlet-class>org.wwc.ammianus.tomcat.tileserver.TileRequestHandler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TileRequestHandler</servlet-name>
<url-pattern>/TileRequestHandler</url-pattern>
</servlet-mapping>
</web-app>
Now I was typically running this from my Eclipse IDE (Eclipse J2EE 3.4.1, Apache Tomcat 6), but I also could export the project in Eclipse as a war and just drop it into Tomcat's webapps folder.

To access this server there is the format that the URL would take:
http://localhost:8080/TomcatTileServer/TileRequestHandler?T=geocover2000&L=0&X=48&Y=21

To break this down:
  • T = the name of the layer, or DataSet name ( tag value from @Images.xml)
  • L = level, (0 - x) where 0 is the highest level
  • X = column
  • Y = row
From this the TileServer, based on its implementation and organization of the images, will try to look up locally a file that matches that. In my case it was something like C:\Users\Public\WorldWindCache\Cache\Earth\Images\NASA Landsat Imagery\Geocover 2000\0\0021\0021_0049.jpg".

Integrating Local Server with WorldWind
Thanks to WorldWind forums for giving me this information. Now to make WorldWind point to my local tile servlet instead of the default NASA WMS server, you need to edit the @Images.xml file in your WorldWind's Config\Earth directory. There is probably an @Images.tmp, copy this and rename it to @Images.xml.

Edit the file, and for the DataSetName your local server will handle, update the tag such as:
<ServerUrl>http://localhost:8080/TomcatTileServer/TileRequestHandler</ServerUrl>
And then restart World Wind you should be good to go

Saturday, June 27, 2009

Vacation

On my way to South Korea! Will be spending my vacation there for the next three weeks.







On the flight I hope to set up my world wind with a local tile server for doing further development on download code. Maybe some more updates soon.

Saturday, April 18, 2009

Java HashMap vs. C# Hashtable

One of the things I have found has been more frustrating while picking up C# .NET for the World Wind project is that some of the simple basic programming constructs that are automatic for me in Java don't seem to be directly parallel in C#. On top of that the online documentation at the MSDN site and other places is either not intuitive or I am looking in the wrong areas.

One of the basic data structures I depend on in Java are Maps. One of the simple classes that implement the Map interface in Java is java.util.HashMap.

Like other data structure objects in Java, there is no special syntax to interact with this object, it has methods like other objects where you pass in arguments and get return values.

The most basic usage of the HashMap generally goes like this:

//construct the new map
HashMap javaMap = new HashMap();
//enter a new key value pair
javaMap.put("key","value");
//to get the all values out of the map
Set keys = javaMap.keySet();
Iterator keyIter = keys.iterator();
while(keyIter.hasNext()){
String key = (String) keyIter.next();
String value = (String) javaMap.get(key);
System.out.println(key+" = "+value);
}






So it is pretty straightforward usage (in my mind), the put method "puts" data into the Map and the "get" method retrieves data from the Map given a key. Great

C# on the other hand uses a more elaborate syntax and combination of properties, keywords and methods. Not that this is more difficult but it took some time for me to figure out for example, that there was no equivalent to the "get" method in Hashtable, that you needed to use the "[]" syntax as if this were like an array

For the equivalent C# as the above, you can use the System.Collections.Hashtable class which implements the IDictionary interface:

//construct the Hashtable
Hashtable cSharpTable = new Hashtable();
//enter new key value pairs
cSharpTable.Add("key", "value");
cSharpTable.Add("hello", "world");
//for all Keys, a public property on Hashtable class, print out the key and value
foreach (String key in cSharpTable.Keys)
{
String value = (String) cSharpTable[key];
System.Console.WriteLine(key + " = " + value);
}


So in some ways the C# code is definitely more concise. But for a Java programmer it feels a bit strange, instead of 3 methods in Java(all with clear Javadoc descriptions of use, IDE auto-complete and tool tips, same syntax as all other method calls in Java etc..) for put(),get(),keySet(), C# requires you to use three different language features, a method, Add(), a property on the object Keys (why not just use a method?), and a [] operator. Granted in Visual Studio 2005 typing "cSharpTable." and you would see a list of the public methods and properties including the Add() and Keys, but you would only see the auto-assist tool-tip if you knew to type "cSharpTable[" and then it would give you the basic description of the syntax "object Hashtable[object key]".

I guess it is just something I'll have to learn.

I basically learned Java on the fly on my first job. I learned it fairly easily because once you got it that everything is just a method its pretty easy to find and locate what you need, plus the clear and standardized format of Javadoc based sites makes learning new classes or finding methods fairly simple. Try comparing the ease of use of Sun's Java API site with Microsoft's MSDN .NET Framework Reference(see link to HashMap and Hashtable classes above). Is it really an apples to oranges comparison? Or is the MSDN site just not very readable (for that one class there is no list of methods, just pages of examples in multiple languages.

References:
Holzner, Steven Microsoft Visual C# .NET 2003 Kick Start. Indianapolis: Sams Publishing, 2004. pp243-245

Saturday, April 11, 2009

Contribution Update

I went back and did some further rework for the changes to the "Download code" I submitted to the forum earlier. I posted these on the forum as well (still do not have commit access to SVN). There were no clear directions so I took some suggestions from forum users and combined that with already existing functionality (that was in the code but not used due to a bug I think I fixed).

I spent this day making these updates. Basically there were 3 files updated.

Changes include:
  • Now individual tiles will be put in a HashTable if they get 3 404 errors. They will be prevented from being readded to the download queue. Pressing 'F5' will clear this HashTable as will restarting the program.
  • After 5 failed tiles download attempts (tiles reaching the status above) the current anti-hammer logic kicks in to prevent further requests to that server for that layer. The default timeout period is 2 minutes before it will try to download for this layer again. Pressing 'Pressing F5' will clear this counter, and will stop the timeout and restart the download queue for this layer.
  • When the above condition is reached it will display a message in the top right saying "Problem connecting to server... Trying again in 2 minutes" when that layer is rendered after a timeout is reached. This stays visible for the first 20 seconds of the timeout then will be fade out...this logic was actually in there currently, but I was able to confirm that you can see it now (plus I extended the time it is visible from 15 to 20 seconds).

Tuesday, April 7, 2009

World Wind 1.4.1 Issues

I reported two more issues based on my work over the weekend. I did not get a whole lot of responses yet.

Issue 1:
I notice that when you uncheck "Starfield" in the Layer Manager, it doesn't actually remove the stars that are in the background.

Response: confirmed issue

Issue 2:
I have noticed this on my new development environment which is Vista (64-bit).

Sometimes, but not every time (can't seem to pinpoint an obvious cause or pattern), after I have run World Wind from VCE2005 and exit it from the File menu, then try to Run it in Debug again it will not start up. There is no Worldwind.exe process running and the problem remains if I just restart Visual Studio.


This was a juicy one, I had seen this before but thought it was some change to the code I had made caused this problem.

Thankfully I found that in WorldWind.cs it is actually checking for a Window handle named 'NASA World Wind', finding one and then returning after sending arguments for it.

I have had to comment out this return. Otherwise I need to log off of Windows and log back on to fix the problem.

The bug is that probably the Window is not being shut down completely.

// If World Wind is already running, pass any commandline
// arguments from this instance, and quit.
IntPtr handle = GetWWHandle();
if (!System.IntPtr.Zero.Equals(handle))
{


if(args.Length>0)
NativeMethods.SendArgs( handle, string.Join("\n",args) );

//[Ammianus] by commenting out this return I can get it to start every time.
//return;
}


Both bugs are being discussed in this stickied thread on the World Wind forums.

First contribution?

Technically I did not check-in any changes to SVN, but I did suggest a fix for World Wind on the forums.

I have been spending a good while looking into the "download code" issue. I have taken a step back and this past weekend I dove into the code using my new development machine.

By tweaking a couple of lines of code I managed to unlock behavior already built in to the download classes that would prevent multiple failed downloads from repeating for a particular layer (after 5 failures, stop downloads for a timeout period of 2 minutes). This was slightly different from the expressed requirement to flag specific tiles for not being found and not retrying those.

So on April 5, 2009, I went back to the World Wind forums and posted my update including the changes to the two class files to make the existing functionality work correctly. I even got some replies by a few active members that they would try it out. I asked for clarification as well if I should go back and make the anti-hammer logic work for tiles specifically rather than whole layers which is what I initially wanted to do.

It was such a successful feeling on Sunday to get this working the way I wanted. My wife and I spent all day working on our various projects, me on World Wind, her on her doctoral dissertation. It took about 5-6 hours of steady work, debugging and reading log files to really wrap my head around how these classes were truly interacting. Making a simple change (which I understood) and having it work was very rewarding, it gives me confidence to continue with some more changes.

Things to check:

* One recommendation was to display a message in the UI that the connection to the server is on hold for the 2 minute timeout period. I did in fact see something like that at one point in my testing but it quickly went away, may have been unrelated to my code changes
* Pressing 'F5' will clear the cache for a specific area and force a retry of the download of the visible tiles. Suggestion was that this should reset any timeout or counters of failures if the user doesn't want to wait (I suppose would be the case if they scrolled back over some location that they were more confident had tiles to download from the server)
* Need validation on whether current anti-hammer logic is ok, or we need per-tile anti-hammer logic

New development machine

Not wanting to abuse my work laptop too much, I decided that for my own personal development I needed a new machine, laptops are relatively cheap these days.

I decided on getting a lower-end machine (which means less on the CPU and Graphics card side, but leaving ample memory and hard disk space). After browsing around different reviews and shopping a bit, I decided to settle on a Toshiba Satellite M305-S4907

Basic specs:
* 2GHz Intel® Pentium® Processor T3400
* 4GB PC6400 DDR2 800MHz SDRAM
* 320GB HDD (5400rpm)
* Windows Vista® Home Premium (SP1, 64-bit)
* 14.1" widescreen display
* 5.2 lbs

It took me a few weekends to get used to how use Windows Vista, but I am really enjoying this pc now. I recommend it. Graphics scored somewhat low on the Windows Vista benchmark, but other than World Wind, I don't really use any graphics intensive applications. Unfortunately, World Wind is fairly graphics intensive and that was one of the primary reasons I bought this laptop, to do open source development when not at home.

Tuesday, March 3, 2009

Asynchronous downloads

One of the things I've learned about the download code is that it uses Asynchronous calls to handle the downloading of the image files from the server in the background.

I found a good article on doing these calls in .NET which explains a lot of the World Wind .NET download code and what it is doing.

http://www.codeproject.com/KB/dotnet/async_pattern.aspx

I need to understand this in order to really implement the more robust queuing method.

Sunday, March 1, 2009

Download code

So I have struggled with the infamous "download code" for the past week or more. It was really difficult to untangle what connects to what and where. I found myself resorting to drawing my own class diagrams to keep the pieces straight from what I could tell.

What was interesting is that there looks like two separate and independent "download code" implementations that do almost the same thing for different areas of the application.

The first component, if you will, was in the project called WebDownload, this was the first one I was able to step my way through. Unfortunately, it was not the component that could solve the problem I was tasked with fixing.


The next set of classes was in another project, PluginSDK. Here was where I eventually made some quick changes to actually stop the repeating downloads from happening.



The QuadTileSet is the center of action here, it has the queue of download requests that it services. I changed this class to have a Hashtable where it would store the download requests for tiles where the server responded with a 404 response. Then it wouldn't re-add these items to the download queue if they were in this Hashtable already.

All in all I had to make some slight changes to three classes here:

  • QuadTileSet

  • GeoSpatialDownloadRequest

  • WebDownload




You may notice the snazzy UML class diagrams I used above. I am not really big on UML, though I used to do class diagrams a lot for a previous company. I went looking for some free, preferably Open Source UML Editors, just to let me crank out the class diagrams above (which I had already hand-drawn on paper).

I tried out two, both were basically Eclipse plugins. One did not work and the other I felt was too complex and buggy for the simple diagrams I want to do.
Papyrus UML - this actually worked but was difficult to use

acceleo - I installed this in my Eclipse environment as a plugin as per directions. I didn't allow me to create any diagrams after about 10 minutes of trying so I uninstalled it.

Sunday, February 22, 2009

Back into the fray

I have been on a hiatus from any of my leisurely coding pursuits. I had some deadlines on my current project for my real job, and spent the majority of the past two weeks and weekends working on finishing up some of those items. I completed most of those items on Friday so I am able to catch my breath and look into WorldWind .NET again.

Since I've been gone there has been discussions of setting up a Jira site for .NET that was apparently taken down right around when I signed up for world wind (yet another sign that I've jumped into an active healthy open-source community ;-)). So latest word is that they will probably shortly set up a new Jira instance on a WorldWind central server, then they will need to get the old Jira data from NASA.

In addition it looks like I've started to receive the emails from SourceForge with logs of everything checked in to SVN. Which is cool. Looks like a couple of members are starting to make modifications and updates. There is also an thread now of open 1.4.1 issues.

There are some issues with the download code for WW it seems. And when it was stated that no developers were around to fix it I stuck my head out again to let them know I was going to be helping soon. Some members wise-cracked that whomever works on the download code disappears in 7 days...

I'll try to spend some time this week, I have a couple of issues going on at work still that might take up my time. But I'm not giving up yet.

Friday, January 30, 2009

Log4j explanation

This article helped me get around a problem at work. It was so simple and so helpful all at once.

Thank you sir!

Specifically what I was trying to do was to find out what logging was being done by some classes I was trying to test with JUnit Testing with an Eclipse plugin. I didn't know how the server I was interacting with was trying to find the log4j properties (what file name at what path) and I was having no luck seeing the log messages for the classes I was trying to test because there was no category set for them.

I would receive warning like this:
log4j:WARN No appenders could be found for logger(somePackageName.someClassName).
log4j:WARN Please initialize the log4j system properly.

In order to add a specific appenders to DEBUG and ERROR level messages from my class I need to find the log4j configuration.

In the Eclipse Debug Configurations on my JUnit test configuration, click on the Arguments tab. For VM Arguments I had the following:
-ea -Xmx256m -Dlog4j.debug

That did the trick, I was able to see in the console a message stating the xxx.properties was not found.
With that information I updated the properties file in the path it was looking for to add a category for the packages under test, and to change the appenders to point to new log files in my Eclipse project.

Monday, January 26, 2009

The Orientalists

Fischer - An Arab Caravan at DuskThe Orientalists by Kristian Davies published in 2005. The book is filled with great art, apparently from Davies descriptions most of it little known and much maligned by the general art "establishment" since the 20th century.

Most of the artists were Europeans who traveled to North Africa, the Middle East and South Asia in search of some escapist inspiration. They painted in a generally traditional, even academic style. The criticism is mainly that they were either cultural elitists, imperialists, racist, sexist or otherwise revisionist. They played up the mystique and lure of the Orient or portrayed the local people and cultures as backward or primitive.

The brief biographies of some of the painters and other adventurers was interesting. I've always had an interest in the grand and fantastic paintings I would occasionally see in museums but never had read, much less been taught, about them in any detail. Of course why else would I go through the trouble of finding this book in a library otherwise?

I found about 20 artists I really liked out of the bunch and made my first foray into true fine art knowledge by writing down their info and finding images of prints of their best paintings from google. In the process, I found a lot of good stuff from wikimedia commons and the internet archive. I had no idea that these sites had such a rich library of content, and in fact had better search results than the crap shoot of google image search.


World Wind Release Mode

After bringing up the issue with the current state of the code in SVN, the bad commit was reverted and now everything compiles and builds without error.

At the same time, Bull from the World Wind Central forums posted a blog about how to build in 'Release' mode.

Building World Wind in Release Mode

Wednesday, January 21, 2009

WW: Progress Update:

After a slow start I got a few answers to my questions:

For WorldWind, the standard for development is Visual Studio 2005. Any changes I made to the project files (say adding a new class file) would need to be checked in by someone else using 2005 for backwards compatibility to all the other 2005 developers.

I was able to download Visual C# 2005 Express for free from Microsoft's site (link while it lasts: http://www.microsoft.com/express/2005/download/default.aspx ). I downloaded it as a CD image and created the installer on a CD I burned with the image.

I finally got around on Monday to uninstalling Visual C# 2008 Express and all its tangled mess of subcomponents. Once I did that I tried to install 2005 version. It complained at first because I already had a version of the .NET Framework 2.0 SDK installed from earlier. As a result I had to uninstall that in order to install 2005, apparently it includes the 2.0 .NET SDK already.

Using Visual Studio 2005 I opened up the World Wind solution and rebuilt it. I did not get any build errors but this has nothing to do with the version of Visual Studio.

It was confirmed that some other developer had checked in a bad version of the code including the wrong gdal_csharp.dll bindings. I had figured this out by looking at the SVN revision history for those dlls and comparing with the classes that actually referenced them. It took a while for people on the forum to respond, and other than one user nobody seemed to care that the build was broken.

Another disappointment was that I found from some posts that the World Wind SVN repository does not allow commits except for a select few users. I guess that makes sense, but I've never worked on an OpenSource project, so I assumed it was something like Wikipedia's model, where anyone can contribute, but moderators/admins could revert harmful changes to the code. I suppose Software is more tricky than encyclopedia articles.

Anyway, in the mean time to get back up to speed on C# and .NET I revisited some of my old .NET projects, including a Tetris game I wrote in 2003 using GDI+ graphics. I also downloaded a tutorial for creating a simple project that uses Managed DirectX to paint the background of a window different colors.

V-day

For the first time in my life we have a President in Office that I have actually voted for.

I feel as if a great weight has been lifted from our backs.

Enough with the pomp and ceremony, time to roll up our sleeves and get to work.

Update:
Can we stop getting emails constantly from the "The Obama-Biden Presidential Transition Project" (info@change.gov)"

I got three emails in 1 day from them. Do I really need an update telling me about Obama's Inaugural Address, the day after it was all over international media from 6:30 am when I woke up until I went to sleep that night?

Monday, January 12, 2009

Wind in my sails

This year as part of one of my 2009 goals, I recently got interested in trying to contribute to World Wind development after downloading a version a couple of years ago. I am primarily a Java developer but I have done C# .NET development on the 1.1 Framework around 2003-2004. In any case I have a goal of being able to contribute here as well as pick up some more knowledge around .NET. Maybe for now I can turn some of my questions or any tips into more detailed documentation for new contributors in the future (more documentation can never hurt right? )

Getting Started


I have the professional version of Visual Studio .NET 2003 (not sure if it can be used with .NET 2.0+ Frameworks).

1)So I started out with installing Visual C# 2008 Express(http://www.microsoft.com/express/product/)

2)Following the wiki
-I downloaded the .NET 2.0 Framework SDK just in case (I am not sure if this necessary: http://www.microsoft.com/downloads/d...displaylang=en)
-Next I got the Nov 2007 DirectX SDK (http://www.microsoft.com/downloads/d...displaylang=en)


3) With tortoiseSVN I checked out the latest code from SVN repo ( https://nasa-exp.svn.sourceforge.net...runk/WorldWind)

4) I opened the solutions file in C# 2008, and had it convert the projects after making a backup.

5) Under Build > Build Configuration I changed the Active Solution Configuration to 'Debug' from 'Debug MSRS' (I don't know if this is needed)

5) I tried to Run the app with Debug > Start Debug. It said there were build errors (more on that later), but I could run last successful build, which I did. So WorldWind started and I pointed its Cache file to my existing installed WorldWind 1.4 cache directory.

Success!

Questions:
My first question is, did I miss anything or do anything i shouldn't have?

Second, I see that the conversion done by VS 2008, changes all the .csproj files in the source. Assuming at some point, I wanted to make some contributions what is the policy on checking in projects? Would a 2008 .csproj be backwards-compatible with VS 2005 developers?

When I right-click on any project in the WorldWind solution in VS and view the Properties window, under Targeted Framework: is shows '.NET Framework 3.5'
- Is this part of the "conversion"?
- In all the documentation I have read, WW 1.4(.1) is on .NET 2.0. Are any changes I make for potential contributions possibly not backwards compatible as a result? Should I manually change each projects' Targeted Framework to 2.0? Is there a way to do this for the entire solution at once and not manually changing it in every single project? What is this setting specifically doing? More research will be needed on my part for this one I think.

Finally the build errors
If I build the project I get about 14 Errors, all in the DstileGUI project.

Errors look like:
Code:
Error 1 The type or namespace name 'GDAL' could not be found
(are you missing a using directive or an assembly reference?)
D:\coding\WorldWind\svn\DstilePlugin\GDALImageStore.cs 37 9 DstileGUI
In the project references are references to gdal_csharp.dll and gdalconst_csharp.dll. There is a using GDAL; statement in these classes.

I tried a few things, which I can elaborate on, but it seems as if there may be some mismatch between the gdal version and the DstileGUI code? This page seems to point out that there new Namespace conventions being used with GDAL for C# in version 1.4.0 and 1.5.0 of GDal.

I wonder if they included the right version of the .dll with the source code?


Still waiting for responses from the World Wind Central forums. The Developers Corner there seem pretty quiet but there are a few other recent threads.