You are currently browsing the category archive for the ‘Uncategorized’ category.
In this video of chapter 7 of “Learning Web Development with Seaside” we look at continuations and subroutine calls.
We launch the Seaside One-Click Experience and create a new component that will present a user interface for selecting a date and time. Add an initialize method to create subcomponents for the date selector and the time selector. Add the #’children’ method to let Seaside know about the subcomponents. Add a setter method to assign initial values to the selection components.
As mentioned earlier, the #’renderContentOn:’ method is the heart of Seaside’s HTML generation. In our new component we will define a form and a table to provide layout (proper CSS formatting will be addressed in a later chapter). The form will consist of labels, the date selector, the time selector, and a submit button. Note that we do not specify the actual HTML widgets to be used for the date and time entry, but allow subcomponents to provide that functionality. This demonstrates code and component reuse.
Finally, we add a #’submit’ method to handle the callback when the user selects a date/time. Note that when the user makes a selection, the #’submit’ method answers the new value. This answer is essentially a subroutine return.
We now have defined the code for a new component. To demonstrate the component, we can register it as an application named ‘when’ and then view the component in a web browser. It will, of course, be more useful to use this component in our FlightInfo application.
To do that we go to the FlightInfoComponent class and add a method to call our new component. When this method is called, it creates a new component, sets the date/time to the current value, and then calls the new component. The new component presents a web page, waits for the user to select a new date/time, and then returns that date/time.
The important thing to note here is that we have called a subroutine and are waiting for it to return from an interaction with the user. This ability to continue execution after a user interaction is what we get from a using a Smalltalk continuation and it is a striking departure from the typical web framework in which execution starts at the beginning for each request.
Now that we have a method to call the date/time selection component, we add a link to the primary user interface to call the new component. We have an anchor with a callback.
We can go to the web browser and view the new component in action. Note that we can select a new date/time and when we return to the primary component, it will be immediately displayed.
when we are done, we can save our Smalltalk code and quit the Seaside One-Click Experience application.
In this video from Chapter 6 of “Learning Web Development with Seaside” we look at how Seaside addresses the common web application challenge of storing application state. We start by launching our Seaside One Click Experience and refactoring our #’renderContentOn:’ method so that the change time links are in a separate method. We then add another anchor to report which flight was selected. Clicking on the anchor evaluates a callback that displays the selected flight using Seaside’s #’inform:’ method.
When we run the application we can view various flights, clicking the “Later” link till we get to a desired flight. We select a flight for August 26 and see that the flight for August 26 was selected. If we use the “Later” link to move to a flight on the 28th, and then use the browser’s back button to move to a flight on the 27th, clicking the “Book flight” link ends up selecting a flight on the 28th because that was the last page rendered by the server (the server doesn’t know that we clicked the browser’s back button).
We can observe the same effect by using two tabs (or windows) in the browser. We view the September 1 flight in one tab and then switch back to the August 28 flight in another tab. Clicking the “Book flight” link again gives us the wrong flight because the server has saved the most recent state which came from the other tab.
Seaside provides a simple way of addressing this common web development problem. We can identify which objects have state that is associated with the page being displayed. When an action takes place on that page, the objects are restored to their original state.
Now we return to the application, click “Later” a few times so that a flight on the 5th is displayed. Click the back button to return to a flight on the 3rd, and click the “Book flight” link. We see that now we correctly get the flight from the 3rd. Likewise, if we use a second tab we can view a flight for the 6th in one tab and still select a flight for the 3rd in the other tab.
This demonstrates the ability Seaside provides for easily associating domain states with specific pages rendered to the client. We can now save our Seaside code.
For more information go to seaside.gemstone.com/tutorial.
In this video we explore some of the tools in Seaside. One remarkable feature is the ability to debug a live web request. We start by introducing a misspelling in a method and observe the Message Not Understood error displayed by Seaside. Clicking on the ‘Debug’ link in the web browser brings up a Smalltalk debugger in which we can not only view the stack, but we can edit the source code. After we correct the error, we can proceed with processing the web request and see the correct page in the web browser.
Seaside also provides a number of web-based tools. When in development mode there is a toolbar at the bottom from which we can open a new tab showing the component surrounded by a “halo” of tools. One tool allows us to view the HTML source. Another allows us to create CSS that styles the component. Another allows us to inspect the component and execute arbitrary Smalltalk code from the web. This code can interact with the component and we can see the results immediately. Finally, there is a source code browser that allows us to edit existing methods and add new methods to our component class. As we edit code, we can use the other web tab to view the results.
In this video from Learning Web Development with Seaside we start on a simple application that will be used for a few more lessons. We create a domain model object for ‘FlightInfo’ that holds a date/time for the flight and a price for the flight. We then create a component to display the model object. For the tutorial PDF see http://seaside.gemstone.com/tutorial.html.
I’ve completed editing and posting the videos from the ‘Scaling Objects for the Enterprise’ presentation at Smalltalks 2009 in Buenos Aires. This post provides a summary list of links:
- What is GemStone?
- Object format and pointers
- Special Objects and Header
- Large Objects
- Repository, Extents, and Object Table
- Component Overview
- Shared Page Cache
- How Gems Create an Object
- How Gems Read an Object
- How Gems Modify an Object
- How A Gem Dereferences an Object
- Commit Record Backlog
- Handling Commit Record Backlog
- Commit Process
- Issues in Concurrency
- Lock Granularity
- Reduced Conflict Classes
- The Stone Process
- Live and Dead Objects
- Nine Steps of Repository-Wide Garbage Collection
- Epoch GC, Offline GC, Multi-machine
- Garbage Collection Q & A
If you cannot get access to YouTube (e.g., due to corporate web policies), you can get the QuickTime files directly from here.
This video records few questions and answers. How effective is the mark-sweep? Which objects will be found? Does garbage collection reduce the size of the extent? How can you reduce the size of the repository? How do you manage a “warm” standby for quick recovery?
This is the final video from the GemStone/S tutorial at the Smalltalks 2009 conference in Buenos Aires.
This short video gives a brief description three topics.
“Epoch” garbage collection is a variation on repository-wide garbage collection in which only objects created or modified during a specified period (“epoch”) are scanned. If young objects are more likely to be dereferenced, then this can be much more efficient than a full database scan.
“Off-Line” garbage collection is a variation on repository-wide garbage collection in which the most time- and resource-consuming steps are done on a backup of the database, with intermediate data structures imported into the main database to complete the process.
Multi-machine configuration allows virtual machines (“Gems”) to run on a host separate from the Stone host. This requires a shared page cache (SPC) on the remote machine, and various extra processes on both hosts. While more complex, it does allow significant scaling—with one customer using hundreds of machines all connected to a single database.
A frequent area of confusion in GemStone/S is the use of ports for the NetLDI when starting a remote gem. The Gem startup process is somewhat complex; describing it takes an hour or so of the Advanced Configuration class. I’ll see if I can condense it…
- A GCI client (Topaz, GemTools, Jade, VW/VA, etc.) contacts the NetLDI on a host/port. The port can be specified by number (e.g., 50377) or by name (e.g., gs64ldi) in which case it should be in the client and server services file with the same name/number. This port is defined implicitly by the name provided to the startnetldi command. If no name is provided, then the default of ‘gs64ldi’ is assumed. This port is unrelated to the port range provided as an optional argument (described later).
- The GCI client requests a service from the NetLDI; generally this is a new Gem using the script ‘gemnetobject’. The NetLDI puts the GCI client “on hold” while it starts up the new Gem. This conversation resumes at step #8.
- The NetLDI listens on a new random port for a callback (see #5).
- The NetLDI starts the Gem and passes it the port number from #3.
- The Gem calls the NetLDI on the port from #3 to request further instructions.
- The NetLDI tells the Gem that a GCI client wishes to make contact and that it should listen for the GCI client. If a port range is specified, then the NetLDI will select a port from the range and tell the new Gem to listen on that port. If no port range is specified then the Gem will allow the OS to pick a port at random.
- Using the connection established in #5, the Gem tells the NetLDI which port it is listening on (from #6). The connection from #5 is then closed.
- The NetLDI returns to the GCI client (using the connection established in #1 and put “on hold” in #2) and tells it what port to use to contact the Gem (the port number from #6). The connection between the GCI client and the NetLDI is then closed.
- The GCI client initiates a call to the Gem on the same host as the NetLDI but on a different port–the port on which the Gem is listening. That port number will be one selected by the NetLDI if a port range is specified or one selected by the OS if no port range is specified.
- The Gem accepts the connection from the GCI client and the GCI client provides login information (Stone NRS, userID, password, etc.).
Note that there are three (3) connections involved: (1) from the GCI client to the NetLDI; (2) from the Gem to the NetLDI; and, (3) from the GCI client to the Gem. The first connection is on the official NetLDI port that should be in the services file for each machine (gs64ldi/50377). The second connection is on a random port and there are no naming issues because it is completely self-contained in one host. The third connection is the one that can be random or can be limited to a particular range (using the -p50378:50378 argument to the startnetldi command). If there is a firewall on the server, then the ports for connections 1 and 3 need to be open to calls initiated from outside the server.
There are additional complexities. If the GCI client and the NetLDI are on the same host, then the named NetLDI does not need to be in the services file. Also, in steps 9/10 there are actually two connections, a primary one and an “out-of-band” connection. Furthermore, I could have gotten some of this wrong, but I think there is enough right to explain the difference between the number in the services file and the number in the port range.
This video starts with a description of “Shadow Objects,” objects for which a newer version has been saved in a later transaction. Then we move to the nine steps of repository-wide garbage collection:
- Mark/sweep (to identify live objects);
- Object table sweep (to create a list of possible dead);
- Record possible dead;
- Voting on possible dead by current gems;
- Finalize voting (on behalf of recent commits);
- Read possible dead objects (cleanup);
- Promote to dead (transition);
- Dead object reclamation; and
- Return of pages and object IDs to the free pool.
Understanding these steps and being able to identify where we are in the process is very important to managing a production database since GC may require significant resources.
Because GemStone Smalltalk does not have a native GUI, most developers use a “client” Smalltalk with some tools that give access to the “server” Smalltalk. Traditionally, this has been GemBuilder for Smalltalk (GBS) installed into a VA Smalltalk or VisualWorks client. With the advent of GLASS (and a no-cost license for GemStone/S 64 Bit), tools are also available for Squeak/Pharo (named GemTools).
Because it is non-trivial to set up a local Squeak/Pharo system, we have provided a pre-build “one-click” download that works on Linux, Macintosh, and Microsoft Windows. Of course, once something like this is made, it is immediately out-of-date and it becomes a challenge to provide updates. Updates to GemTools itself, while significant, are at least confined to executing Smalltalk code in the client. Updates to the client environment are, however, more complex. Also, there are those who want to build things from scratch so as to better understand what is going on.
A further complication is that once you a working environment, you are less likely to rebuild it from scratch. This leaves the frustrating experience that “it works for me” and “when I followed the instructions I get a different result.” In our case, the instructions refer to third-parties (the Squeak/Pharo web sites) and simply direct you to follow their download and install instructions. When those instructions change—or the things being installed change—the results are likely to change (and not for the better!). It was into this pit that Friedrich fell a few days ago. He faithfully followed the instructions, but got a different result from those of us who followed the instructions sometime earlier.
Given that Squeak/Pharo is an open-source project and is rapidly developing (and diverging?), keeping GemTools up-to-date is a major challenge. One of the biggest challenges is related to the external library that is used on the client to interact with the server. The name and location of the library seems to be different for each platform and VM. Debugging these problems is particularly challenging, since one gets little more than the error “Unable to find function address.”
As of the date of this blog post, the Pharo download page provides two sources for a client virtual machine. One takes you to a place to get builds of Squeak-184.108.40.2065 for various operating systems, including Linux; the other immediately downloads pharo-vm-0.15.2f-linux.zip. If you take the “Pharo” VM, things work; if you take Squeak-220.127.116.115, then things don’t work. It turns out that the latest Squeak VM has a change in how external libraries are referenced.
When the new VM was released, Ian Piumarta included a release note:
Plugin search stretegy rationalised and simplified. Default location is now the executable directory (where ‘squeakvm’ is installed). The -plugins argument can be a colon-separated list of locations to search, just like PATH. Plugins are named ‘so.plugin’ to make interference with FFI libraries less likely.
Thus, we need to change not just the location of the library, but also its name. Instead of putting ‘gciForLinux.so’ next to the image, you now need to put ‘so.gciForLinux’ next to the virtual machine. Furthermore, when opening the library you need to leave off the ‘so.’ prefix.
So, if you are using Squeak-18.104.22.1685, put ‘so.gciForLinux’ next to the VM, and edit GciLibrary>>#’moduleName’ as follows:
| path |
self isOnWindows ifTrue: [^'gciForWindows.dll'].
self isOnMacintosh ifTrue: [^'gciForMacintosh.so'].
self isOnLinux ifFalse: [self error: 'Unknown platform!'].
path := SmalltalkImage current vmPath , 'so.gciForLinux'.
(FileDirectory new fileExists: path) ifTrue: [^'gciForLinux'].
Once this is done, the client should be able to interact with the GCI library. We should be able to update GemTools with this method soon.