<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3795037690945695493</id><updated>2012-02-04T18:58:56.028-05:00</updated><category term='GPU'/><category term='compound-variable'/><category term='Fedora'/><category term='Plymouth'/><category term='alarm'/><category term='bootable'/><category term='SpiderMonkey'/><category term='dd'/><category term='C'/><category term='blogspot'/><category term='Xinerama'/><category term='Google Charts'/><category term='date'/><category term='ToolTalk'/><category term='linux capabilities'/><category term='Flointing point'/><category term='RSS'/><category term='custom builtins'/><category term='XAM'/><category term='IEEE 1003.1'/><category term='XSet'/><category term='The Open Group'/><category term='FireFox'/><category term='CTP3'/><category term='half precision'/><category term='XSLT'/><category term='Accounting'/><category term='XSL'/><category term='XStream'/><category term='HPET'/><category term='XML'/><category term='XML  ARRAYS'/><category term='XOP'/><category term='printf'/><category term='ksh93'/><category term='POSIX'/><category term='display source code'/><category term='I/O'/><category term='IEEE 754'/><category term='TwinView'/><category term='Lenovo'/><category term='NSPR'/><category term='regular expressions'/><category term='D-Bus'/><category term='JavaScript'/><category term='builtin'/><category term='extended patterns'/><category term='Python'/><category term='Vista'/><category term='Linux Windows Porting WaitForSingleObject  NtWaitForSingleObject WaitForMultipleObject NtWaitForMultipleObject threads mutex mutant'/><category term='Favicon'/><category term='Automatic voice translation'/><category term='stat'/><category term='Podcasts'/><category term='Auditing'/><category term='SimpleDB'/><category term='GOOGLE TRANSLATE'/><category term='E4X'/><category term='JS'/><category term='capget'/><category term='GNOME'/><category term='C++'/><category term='Shell'/><category term='PowerShell'/><category term='POSIX.1e'/><category term='XSystem'/><category term='CUDA'/><category term='CTP2'/><category term='TraceMonkey'/><category term='Extended Attributes'/><category term='Grady Booch'/><category term='KDE'/><category term='MIME'/><category term='shell script'/><category term='HAL'/><category term='Windows parallel filesystem'/><category term='capset'/><category term='SNIA'/><category term='subvariable'/><category term='bit manipulation'/><category term='nouveau'/><category term='Java'/><category term='CDROM'/><category term='Tomboy'/><category term='FireBug'/><category term='NVIDIA'/><category term='Fedora 11'/><category term='AWS'/><category term='Snipping Tool'/><category term='MTTR'/><category term='Ruby'/><category term='Linux Porting WaitForSingleObject WaitForMultipleObject thread event'/><category term='SUA'/><category term='Linux'/><category term='CCL'/><category term='ksh93 L10N I18N localization message catalog'/><category term='ECMAscript'/><title type='text'>Musings of an OS Plumber</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>58</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-8855010749456968790</id><published>2009-12-17T17:47:00.007-05:00</published><updated>2009-12-19T13:41:04.652-05:00</updated><title type='text'>ksh93 libshell</title><content type='html'>In a number of posts about a year ago I discussed how to develop custom builtins for Korn Shell 93 (ksh93) using &lt;i&gt;libshell&lt;/i&gt; and published APIs. You can also use these same APIs to access ksh93 functionality from within a C application. This post provides three simple examples of how to do this.&lt;br /&gt;&lt;br /&gt;The first example simply takes two numbers as arguments on the command line, multiplies the numbers and prints out the result on &lt;i&gt;stderr&lt;/i&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#include &amp;lt;shell.h&amp;gt;&lt;br /&gt;#include &amp;lt;nval.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    Namval_t *np;&lt;br /&gt;    Sfdouble_t res;&lt;br /&gt;&lt;br /&gt;    Shell_t *shp = sh_init(argc, argv, 0);&lt;br /&gt;    sh_trap("((xresult=$0*$1))", 0);&lt;br /&gt;&lt;br /&gt;    np = nv_open("xresult", shp-&gt;var_tree, 0);&lt;br /&gt;    res = nv_getnum(np);&lt;br /&gt;    sfprintf(sfstderr,"%Lg\n", res);&lt;br /&gt;    nv_close(np);&lt;br /&gt;&lt;br /&gt;    return(0);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;Here is how to compile this example using static libraries. I built these examples in my home directory but the ksh93 build environment is at &lt;i&gt;/work/ksh93&lt;/i&gt;, hence the use of &lt;i&gt;-I&lt;/i&gt; and &lt;i&gt;-L&lt;/i&gt; options. Note the large number of AST (Advanced Software Toolkit) and ksh93 libraries you have to specify in order to resolve all the symbols. &lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;gcc -o example1 -I/work/ksh93/arch/linux.i386-64/include/ast example1.c -L/work/ksh93/arch/linux.i386-64/lib -lshell -lm -ldll -lcmd  -ldl -last &lt;/pre&gt;&lt;/div&gt;For example:&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ ./example1 3 4 &lt;br /&gt;12&lt;br /&gt;$ &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;The next example breaks the text string &lt;i&gt;string&lt;/i&gt; into its component parts and prints them out to &lt;i&gt;stdout&lt;/i&gt;. Note that "foo\\ bar" is one word, not two words.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#include &amp;lt;shell.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;nval.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    char tmp[512];&lt;br /&gt;    char string[] ="hello world 'my name is Finnbarr' foo\\ bar";&lt;br /&gt;&lt;br /&gt;    sprintf(tmp, "set - %s &amp;&amp; for i in \"$@\";\n do\n echo \"$i\"\ndone", string);&lt;br /&gt;&lt;br /&gt;    Shell_t *shp = sh_init(argc, argv, 0);&lt;br /&gt;    sh_trap(tmp, 0);&lt;br /&gt;&lt;br /&gt;    return(0);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;Here is the output:&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;./example2&lt;br /&gt;hello&lt;br /&gt;world&lt;br /&gt;my name is Finnbarr&lt;br /&gt;foo bar&lt;/pre&gt;&lt;/div&gt;The next example is similar to the previous example, except that it creates an array and then uses &lt;i&gt;nv_getval()&lt;/i&gt; to access the contents of the created array and print the contents to &lt;i&gt;stderr&lt;/i&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#include &amp;lt;shell.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;nval.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int &lt;br /&gt;shell(int argc, char* argv[], char *str)&lt;br /&gt;{&lt;br /&gt;    Namval_t *np, *np_sub;&lt;br /&gt;    char tmp[512];&lt;br /&gt;&lt;br /&gt;    sprintf(tmp, "set - %s &amp;&amp; for i in \"$@\";\n do\n aname+=(\"$i\")\ndone", str);&lt;br /&gt;&lt;br /&gt;    Shell_t *shp = sh_init(argc, argv, 0);&lt;br /&gt;    sh_trap(tmp, 0);&lt;br /&gt;&lt;br /&gt;    np = nv_open("aname", shp-&gt;var_tree, 0);&lt;br /&gt;    nv_putsub(np, NULL, ARRAY_SCAN);&lt;br /&gt;    np_sub = np;&lt;br /&gt;&lt;br /&gt;    do {&lt;br /&gt;        // copy out the arguments to wherever here. &lt;br /&gt;        fprintf(stderr, "%d: subscript='%s' value='%s'\n", np_sub, nv_getsub(np_sub), nv_getval(np_sub));&lt;br /&gt;    } while (np_sub &amp;&amp; nv_nextsub(np_sub)); &lt;br /&gt;&lt;br /&gt;    nv_close(np);&lt;br /&gt;&lt;br /&gt;    return(0);&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;int &lt;br /&gt;main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    char string[] ="hello world 'my name is simon' foo\\ bar";&lt;br /&gt;&lt;br /&gt;    shell(argc, argv, string);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;Here is the output:&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ ./example1&lt;br /&gt;37212336: subscript='0' value='hello'&lt;br /&gt;37212336: subscript='1' value='world'&lt;br /&gt;37212336: subscript='2' value='my name is simon'&lt;br /&gt;37212336: subscript='3' value='foo bar'&lt;br /&gt;$ &lt;/pre&gt;&lt;/div&gt;As you can see, running shell script snippets from within a C application is not difficult. For more information on these APIs read the ksh93 &lt;i&gt;shell(3)&lt;/i&gt; and &lt;i&gt;nval(3)&lt;/i&gt; man pages.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-8855010749456968790?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/8855010749456968790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/12/ksh93-libshell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8855010749456968790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8855010749456968790'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/12/ksh93-libshell.html' title='ksh93 libshell'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-8811076979301655306</id><published>2009-11-10T18:50:00.024-05:00</published><updated>2009-11-11T11:28:39.185-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='SUA'/><category scheme='http://www.blogger.com/atom/ns#' term='SpiderMonkey'/><title type='text'>Microsoft SUA JavaScript Shell</title><content type='html'>Recently I needed to test some JavaScript code on a Microsoft Vista Ultimate operating system using the command line. This is something that I have done before on Linux platforms using a JavaScript shell but had never done on a Microsoft platform. For those who are not familiar with a JavaScript shell, it is a command line interface to a JavaScript engine. Similar to Python or Ruby, the JavaScript shell has two modes of operation. You can use it as an interactive shell, in which you type JavaScript code at a prompt and get instant results, or you can invoke a JavaScript program.&lt;br /&gt;&lt;br /&gt;The easiest way that I know of to build a JavaScript shell is to download and build the &lt;a href='http://www.mozilla.org/js/spidermonkey/'&gt;SpiderMonkey&lt;/a&gt; JavaScript engine which comes with a JavaScript Shell. SpiderMonkey is one of two JavaScript engines which the Mozilla software project supports. It is used in the Firefox browser and elsewhere.  The other JavaScript engine is &lt;a href='http://developer.mozilla.org/en/Rhino'&gt;Rhino&lt;/a&gt;.  Rhino is written using the Java language whereas SpiderMonkey is a pure C language implementation which conforms to ECMA-262 Edition 3. Included in SpiderMonkey is a JavaScript &lt;a href='https://developer.mozilla.org/En/SpiderMonkey/Introduction_to_the_JavaScript_shell'&gt;shell&lt;/a&gt;. Source code for both JavaScript engines is readily available on the Mozilla website.&lt;br /&gt;&lt;br /&gt;For Microsoft Vista I had a choice of either building a native Windows executable which could be accessed via the Vista command prompt (similar to the old DOS prompt) or, because Vista Ultimate comes with &lt;a href='http://technet.microsoft.com/en-us/library/cc779522%28WS.10%29.aspx'&gt;Subsystem for Unix-based Applications&lt;/a&gt; (SUA), a shell which was accessable via a more familar Unix-like environment. I choice to go the SUA route.&lt;br /&gt;&lt;br /&gt;Many people are unaware of Microsoft's SUA offering. Basicly it is a full-featured POSIX-compliant subsystem for Windows NT-based operating systems. For their own reasons, Microsoft limits the availablity of SUA to certain products such as Vista Enterprise and Ultimate editions and Windows Server 2008.  It comes with hundreds of utilities including the GNU compiler collection, Korn shell, and development headers and libraries. See &lt;a href='http://www.microsoft.com/downloads/details.aspx?FamilyId=93FF2201-325E-487F-A398-EFDE5758C47F&amp;displaylang=en'&gt;here&lt;/a&gt; for further information.&lt;br /&gt;&lt;br /&gt;SUA is a subsystem which runs natively on top of the Windows kernel. which was orginally developed by Softway Systems. The original name for the product was OpenNT but that was later changed to Interix. Interix and most of the development team was acquired by Microsoft in 1999 and the product was renamed Services For Unix (SFU) in 2005. With the release of Microsft Vista, it was integrated into the operating system as a separate installable component and was renamed Subsystem for Unix-based Applications. There is an active &lt;a href='http://www.interopsystems.com/community/'&gt;user community&lt;/a&gt; around SUA which is hosted by &lt;a href='http://www.interopsystems.com/'&gt;Interop Systems&lt;/a&gt; and sponsored by Microsoft.&lt;br /&gt;&lt;br /&gt;This is the &lt;i&gt;Makefile&lt;/i&gt; which I hacked together to build a static &lt;i&gt;js&lt;/i&gt; executable from the &lt;a href='https://developer.mozilla.org/En/SpiderMonkey/1.8'&gt;SpiderMonkey 1.8&lt;/a&gt; sources for use with Microsoft Vista SUA. &lt;br /&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;JSVERSION = js-1.8.0&lt;br /&gt;&lt;br /&gt;CC = gcc&lt;br /&gt;&lt;br /&gt;OS_ARCH    := $(subst /,_,$(shell uname -s | sed /\ /s//_/))&lt;br /&gt;OS_RELEASE := $(shell uname -r)&lt;br /&gt;OS_CONFIG  := $(OS_ARCH)$(OS_RELEASE)&lt;br /&gt;OBJDIR      = ./$(OS_CONFIG)&lt;br /&gt;&lt;br /&gt;DEFINES     = -DXP_UNIX -DPOSIX_SOURCE -DHAVE_LOCALTIME_R&lt;br /&gt;&lt;br /&gt;LIBDIR     := lib&lt;br /&gt;INCLUDES   += -I$(OBJDIR)&lt;br /&gt;RANLIB      = ranlib&lt;br /&gt;LDFLAGS     = -lm&lt;br /&gt;&lt;br /&gt;OPTIMIZER   =&lt;br /&gt;INTERP_OPTIMIZER =&lt;br /&gt;&lt;br /&gt;CFLAGS          =  $(OPTIMIZER) $(DEFINES) $(INCLUDES)&lt;br /&gt;INTERP_CFLAGS   = $(INTERP_OPTIMIZER) $(DEFINES) $(INCLUDES)&lt;br /&gt;&lt;br /&gt;PREDIRS += editline&lt;br /&gt;DEFINES += -DEDITLINE&lt;br /&gt;&lt;br /&gt;JS_CFILES =     jsapi.c jsarena.c jsarray.c jsatom.c jsbool.c jscntxt.c jsdate.c \&lt;br /&gt;                jsdbgapi.c jsdhash.c jsdtoa.c jsemit.c jsexn.c jsfun.c jsgc.c jshash.c \&lt;br /&gt;                jsinterp.c jsinvoke.c jsiter.c jslock.c jslog2.c jslong.c jsmath.c \&lt;br /&gt;                jsnum.c jsobj.c jsopcode.c jsparse.c jsprf.c jsregexp.c jsscan.c \&lt;br /&gt;                jsscope.c jsscript.c jsstr.c jsutil.c jsxdrapi.c jsxml.c prmjtime.c&lt;br /&gt;&lt;br /&gt;JS_HFILES =     jsarray.h jsatom.h jsbool.h jsconfig.h jscntxt.h jsdate.h \&lt;br /&gt;                jsemit.h jsexn.h jsfun.h jsgc.h jsinterp.h jsiter.h jslibmath.h \&lt;br /&gt;                jslock.h jsmath.h jsnum.h jsobj.h jsopcode.h jsparse.h jsarena.h \&lt;br /&gt;                jsclist.h jsdhash.h jsdtoa.h jshash.h jslong.h jstypes.h jsprvtd.h \&lt;br /&gt;                jspubtd.h jsregexp.h jsscan.h jsscope.h jsscript.h jsstr.h jsutil.h \&lt;br /&gt;                jsxdrapi.h jsxml.h&lt;br /&gt;&lt;br /&gt;API_HFILES =    jsapi.h jsdbgapi.h&lt;br /&gt;&lt;br /&gt;OTHER_HFILES =  jsbit.h jscompat.h jscpucfg.h jsotypes.h jsstddef.h jsopcode.tbl \&lt;br /&gt;                jsproto.tbl js.msg jsshell.msg jskeyword.tbl prmjtime.h resource.h&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;ifdef JS_HAS_FILE_OBJECT&lt;br /&gt;JS_CFILES += jsfile.c&lt;br /&gt;JS_HFILES += jsfile.h&lt;br /&gt;endif&lt;br /&gt;&lt;br /&gt;LIB_CFILES  = $(JS_CFILES)&lt;br /&gt;PROG_CFILES = js.c&lt;br /&gt;&lt;br /&gt;LIB_OBJS  = $(addprefix $(OBJDIR)/, $(LIB_CFILES:.c=.o))&lt;br /&gt;PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CFILES:.c=.o))&lt;br /&gt;&lt;br /&gt;CFILES = $(LIB_CFILES) $(PROG_CFILES)&lt;br /&gt;OBJS   = $(LIB_OBJS) $(PROG_OBJS)&lt;br /&gt;&lt;br /&gt;LIBRARY = $(OBJDIR)/libjs.a&lt;br /&gt;PROGRAM = $(OBJDIR)/js&lt;br /&gt;TARGETS = $(PROGRAM)&lt;br /&gt;&lt;br /&gt;EDIT_LIBRARY  = $(OBJDIR)/libedit.a&lt;br /&gt;EDIT_DIR      = ./editline&lt;br /&gt;EDIT_CFILES   = $(EDIT_DIR)/editline.c $(EDIT_DIR)/sysunix.c&lt;br /&gt;EDIT_OBJS     = $(OBJDIR)/editline.o $(OBJDIR)/sysunix.o&lt;br /&gt;EDIT_CFLAGS   = -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX \&lt;br /&gt;                -DHAVE_STDLIB -DUNIQUE_HISTORY $(DEFINES) -I$(EDIT_DIR)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;define MAKE_OBJDIR&lt;br /&gt;if test ! -d $(@D); then rm -rf $(@D); mkdir -p $(@D); fi&lt;br /&gt;endef&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;all:&lt;br /&gt;        $(MAKE) $(TARGETS)&lt;br /&gt;&lt;br /&gt;$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(EDIT_LIBRARY)&lt;br /&gt;        $(CC) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(EDIT_LIBRARY) $(LDFLAGS)&lt;br /&gt;&lt;br /&gt;$(OBJDIR)/%.o: %.c %.h&lt;br /&gt;        @$(MAKE_OBJDIR)&lt;br /&gt;        $(CC) -o $@ -c $(CFLAGS) $*.c&lt;br /&gt;&lt;br /&gt;$(OBJDIR)/editline.o: $(EDIT_DIR)/editline.c $(EDIT_DIR)/editline.h&lt;br /&gt;        @$(MAKE_OBJDIR)&lt;br /&gt;        $(CC) -o $@ -c $(EDIT_CFLAGS) $(EDIT_DIR)/editline.c&lt;br /&gt;&lt;br /&gt;$(OBJDIR)/sysunix.o: $(EDIT_DIR)/sysunix.c $(EDIT_DIR)/editline.h&lt;br /&gt;        @$(MAKE_OBJDIR)&lt;br /&gt;        $(CC) -o $@ -c $(EDIT_CFLAGS) $(EDIT_DIR)/sysunix.c&lt;br /&gt;&lt;br /&gt;$(OBJDIR)/%.o: %.c&lt;br /&gt;        @$(MAKE_OBJDIR)&lt;br /&gt;        $(CC) -o $(OBJDIR)/jscpucfg jscpucfg.c&lt;br /&gt;        $(OBJDIR)/jscpucfg &gt; $(OBJDIR)/jsautocfg.h&lt;br /&gt;        $(CC) -o $(OBJDIR)/jskwgen jskwgen.c&lt;br /&gt;        $(OBJDIR)/jskwgen $(OBJDIR)/jsautokw.h&lt;br /&gt;        $(CC) -o $@ -c $(CFLAGS) $*.c&lt;br /&gt;&lt;br /&gt;$(OBJDIR)/jsinterp.o: jsinterp.c jsinterp.h&lt;br /&gt;        @$(MAKE_OBJDIR)&lt;br /&gt;        $(CC) -o $@ -c $(INTERP_CFLAGS) jsinterp.c&lt;br /&gt;&lt;br /&gt;$(EDIT_LIBRARY): $(EDIT_OBJS)&lt;br /&gt;        $(AR) rv $@ $?&lt;br /&gt;        $(RANLIB) $@&lt;br /&gt;&lt;br /&gt;$(LIBRARY): $(LIB_OBJS)&lt;br /&gt;        $(AR) rv $@ $?&lt;br /&gt;        $(RANLIB) $@&lt;br /&gt;&lt;br /&gt;clean:&lt;br /&gt;        rm -rf $(OBJS)&lt;br /&gt;&lt;br /&gt;clobber:&lt;br /&gt;        rm -rf $(OBJDIR)&lt;br /&gt;&lt;br /&gt;tarball:&lt;br /&gt;        mkdir -p ./$(JSVERSION)/editline&lt;br /&gt;        cp *.[ch] ./$(JSVERSION)&lt;br /&gt;        cp *.tbl ./$(JSVERSION)&lt;br /&gt;        cp *.js ./$(JSVERSION)&lt;br /&gt;        cp *.msg ./$(JSVERSION)&lt;br /&gt;        cp Makefile ./$(JSVERSION)&lt;br /&gt;        cp README ./$(JSVERSION)&lt;br /&gt;        cp editline/*.[ch] ./$(JSVERSION)/editline&lt;br /&gt;        cp editline/README ./$(JSVERSION)/editline&lt;br /&gt;        cp editline/editline.3 ./$(JSVERSION)/editline&lt;br /&gt;        tar cvf $(JSVERSION).tar ./$(JSVERSION)&lt;br /&gt;        gzip $(JSVERSION).tar&lt;br /&gt;        rm -rf ./$(JSVERSION)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note you need to use gcc 4.2 instead of gcc 3.2 otherwise you will get an undefined &lt;i&gt;_JS_DHashTableOperate&lt;/i&gt; symbol due to an obsure gcc bug. However with gcc 4.2, you will see a large number of compiler warnings relating to alignment is greater than maximum object file. Fortunately you can safely ignore them. By the way, I choose to build a static executable because building shared libraries on SUA using gcc is somewhat problematic.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_IrJjVkDo0pg/SvrlMF0eFEI/AAAAAAAAAHc/Am424a0dr6w/s1600-h/javascript1.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 650px; height: 350px;" src="http://3.bp.blogspot.com/_IrJjVkDo0pg/SvrlMF0eFEI/AAAAAAAAAHc/Am424a0dr6w/s320/javascript1.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5402882698867774530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once you have build an executable, a simple smoketest is to use the executable to execute the &lt;i&gt;prefect.js&lt;/i&gt; JavaScript script which is included with the SpiderMonkey source code. You should get output similar to the following:&lt;br /&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ ./Interix6.0/js perfect.js&lt;br /&gt;&lt;br /&gt;A number is 'perfect' if it is equal to the sum of its&lt;br /&gt;divisors (excluding itself).&lt;br /&gt;&lt;br /&gt;The perfect numbers up to 500 are:&lt;br /&gt;6 = 1 + 2 + 3&lt;br /&gt;28 = 1 + 2 + 4 + 7 + 14&lt;br /&gt;496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248&lt;br /&gt;That's all.&lt;br /&gt;$&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Well, this should be enough to enable you to build your own JavaScript shell on Microsoft's Subsystem for Unix-based Applications. Good Luck!&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-8811076979301655306?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/8811076979301655306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/11/javascript-under-interix.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8811076979301655306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8811076979301655306'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/11/javascript-under-interix.html' title='Microsoft SUA JavaScript Shell'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_IrJjVkDo0pg/SvrlMF0eFEI/AAAAAAAAAHc/Am424a0dr6w/s72-c/javascript1.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-3695172439366777243</id><published>2009-10-10T00:15:00.019-04:00</published><updated>2009-12-06T22:53:23.634-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CUDA'/><category scheme='http://www.blogger.com/atom/ns#' term='NVIDIA'/><title type='text'>Inverting Large Images Using CUDA</title><content type='html'>This is a simple example of how to invert a very large image, stored as a &lt;i&gt;vector&lt;/i&gt; using nVidia's &lt;a href='//www.nvidia.com/object/cuda_home.html'&gt;CUDA&lt;/a&gt; programming environment and an EVGA GeForce GTX 260 graphics card. &lt;br /&gt;&lt;br /&gt;A GeForce GTX 260 card should have only 24 cores on it, but the nVidia SDK &lt;i&gt;deviceQuery&lt;/i&gt; utility reports that there are 27 multiprocessors on my GeForce GTX 260 graphics card and I am able to use all 27 of them.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ deviceQuery&lt;br /&gt;CUDA Device Query (Runtime API) version (CUDART static linking)&lt;br /&gt;There is 1 device supporting CUDA&lt;br /&gt;&lt;br /&gt;Device 0: "GeForce GTX 260"&lt;br /&gt;  CUDA Driver Version:                           2.30&lt;br /&gt;  CUDA Runtime Version:                          2.30&lt;br /&gt;  CUDA Capability Major revision number:         1&lt;br /&gt;  CUDA Capability Minor revision number:         3&lt;br /&gt;  Total amount of global memory:                 938803200 bytes&lt;br /&gt;  Number of multiprocessors:                     27&lt;br /&gt;  Number of cores:                               216&lt;br /&gt;  Total amount of constant memory:               65536 bytes&lt;br /&gt;  Total amount of shared memory per block:       16384 bytes&lt;br /&gt;  Total number of registers available per block: 16384&lt;br /&gt;  Warp size:                                     32&lt;br /&gt;  Maximum number of threads per block:           512&lt;br /&gt;  Maximum sizes of each dimension of a block:    512 x 512 x 64&lt;br /&gt;  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1&lt;br /&gt;  Maximum memory pitch:                          262144 bytes&lt;br /&gt;  Texture alignment:                             256 bytes&lt;br /&gt;  Clock rate:                                    1.35 GHz&lt;br /&gt;  Concurrent copy and execution:                 Yes&lt;br /&gt;  Run time limit on kernels:                     Yes&lt;br /&gt;  Integrated:                                    No&lt;br /&gt;  Support host page-locked memory mapping:       Yes&lt;br /&gt;  Compute mode:                                  Default (multiple host threads can use this device simultaneously)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;The application is fairly trivial. It reads in an image file in PPM P6 format,  stores the image in a vector of integers, one per pixel, with 24-bits used to store the RGB values. Depending on which command line option is selected ( &lt;i&gt;-c&lt;/i&gt; invert using CPU, &lt;i&gt;-g&lt;/i&gt; invert using GPU), it then inverts the image vector either using the CPU or the GPU (Graphical Processing Unit).  Finally it writes the image out to an output file in PPM P6 format. &lt;br /&gt;&lt;br /&gt;It uses a block size of 16 and a single kernel called &lt;i&gt;myCudaInvertPixel&lt;/i&gt; which works on 16 rows of the image at the time via tiling.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;fstream&amp;gt;&lt;br /&gt;#include &amp;lt;sstream&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;#include &amp;lt;climits&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;time.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;cuda.h&amp;gt;&lt;br /&gt;#include &amp;lt;cuda_runtime_api.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#define BLOCK_SIZE 16&lt;br /&gt;// #define DEBUG 0&lt;br /&gt;&lt;br /&gt;// ------------ prototypes --------------&lt;br /&gt;__global__ void myCudaInvertPixel(int *, int);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class CCL {&lt;br /&gt;&lt;br /&gt;    int width;&lt;br /&gt;    int height;&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;    CCL() { width = height = 0; }&lt;br /&gt;    ~CCL() { width = height = 0; }&lt;br /&gt;&lt;br /&gt;    void cuda_ccl(vector&lt;int&gt;&amp; img, int w)&lt;br /&gt;    {&lt;br /&gt;        width = w;&lt;br /&gt;        height = img.size()/w;&lt;br /&gt;&lt;br /&gt;#ifdef DEBUG&lt;br /&gt;        cout &amp;lt;&amp;lt; "Image width=" &amp;lt;&amp;lt; width &amp;lt;&amp;lt; " height=" &amp;lt;&amp;lt; height &amp;lt;&amp;lt; endl;&lt;br /&gt;#endif        &lt;br /&gt;        int result = cuda_invert(img, width, height);&lt;br /&gt;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;    int cuda_invert(vector&lt;int&gt;&amp;, int, int);&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;CCL::cuda_invert(vector&lt;int&gt;&amp; image, int width, int height)&lt;br /&gt;{&lt;br /&gt;    int deviceCount = 0;&lt;br /&gt;    int driverVersion = 0, runtimeVersion = 0;&lt;br /&gt;    int globalMem;&lt;br /&gt;    int image_size = width * height * sizeof(int);&lt;br /&gt;&lt;br /&gt;    int *cuda_image_ptr;&lt;br /&gt;    cudaDeviceProp deviceProp;&lt;br /&gt;    cudaError_t err;&lt;br /&gt;&lt;br /&gt;    int strake_size = 0;&lt;br /&gt;    int last_strake_size = 0;&lt;br /&gt;    int strakes = 0;&lt;br /&gt;    int this_strake_size = 0;&lt;br /&gt;    int offset = 0;&lt;br /&gt;&lt;br /&gt;    if (cudaGetDeviceCount(&amp;deviceCount) != cudaSuccess) {&lt;br /&gt;        printf("ERROR: cudaGetDeviceCount failed. CUDA Driver and Runtime version may be mismatched.\n");&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (deviceCount == 0) {&lt;br /&gt;        printf("ERROR: No device supporting CUDA found\n");&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    cudaGetDeviceProperties(&amp;deviceProp, 0);&lt;br /&gt;    globalMem = deviceProp.totalGlobalMem;&lt;br /&gt;&lt;br /&gt;#ifdef DEBUG &lt;br /&gt;    printf("Number of CUDA devices: %d\n\n", deviceCount);&lt;br /&gt;    printf("Device %d: \"%s\"\n", 0, deviceProp.name);&lt;br /&gt;#if CUDART_VERSION &amp;gt;= 2020&lt;br /&gt;    cudaDriverGetVersion(&amp;driverVersion);&lt;br /&gt;    cudaRuntimeGetVersion(&amp;runtimeVersion);&lt;br /&gt;    printf("  CUDA Driver Version:                   %d.%d\n", driverVersion/1000, driverVersion%100);&lt;br /&gt;    printf("  CUDA Runtime Version:                  %d.%d\n", runtimeVersion/1000, runtimeVersion%100);&lt;br /&gt;#endif&lt;br /&gt;    printf("  CUDA capability revision number:       %d.%d\n", deviceProp.major, deviceProp.minor);&lt;br /&gt;#if CUDART_VERSION &amp;gt;= 2000&lt;br /&gt;    printf("  Number of multiprocessors:             %d\n", deviceProp.multiProcessorCount);&lt;br /&gt;    printf("  Number of cores:                       %d\n", 8 * deviceProp.multiProcessorCount);&lt;br /&gt;    printf("  Maximum number of threads per block:   %d\n", deviceProp.maxThreadsPerBlock);&lt;br /&gt;#endif&lt;br /&gt;    printf("  Clock rate:                            %.2f GHz\n", deviceProp.clockRate * 1e-6f);&lt;br /&gt;    printf("  Global memory:                         %d\n", globalMem);&lt;br /&gt;    printf("  Shared memory per block:               %d\n", deviceProp.sharedMemPerBlock);&lt;br /&gt;    printf("  Registers per block:                   %d\n\n", deviceProp.regsPerBlock);&lt;br /&gt;#endif    &lt;br /&gt;&lt;br /&gt;    cudaSetDevice(0);      // not needed - default is 0.&lt;br /&gt;&lt;br /&gt;    int rowBytes = width * 4;                                                       // size of a row&lt;br /&gt;    int maxrow  = BLOCK_SIZE;                                                       // max rows that can be handled in global memory&lt;br /&gt;    strake_size = maxrow * rowBytes;                                                // memory to allocate&lt;br /&gt;    strakes = image_size/strake_size + ((image_size % strake_size == 0) ? 0 : 1);   // there X strakes necessary&lt;br /&gt;    last_strake_size = image_size - (strake_size * (strakes - 1));                  // figure out size of last strake (may be smaller)&lt;br /&gt;#if DEBUG&lt;br /&gt;    printf("  Image size %d\n", image_size);&lt;br /&gt;    printf("  Image vector size %d\n", image.size());&lt;br /&gt;    printf("  Row size %d\n", rowBytes);&lt;br /&gt;    printf("  Maxximum rows %d\n", maxrow);&lt;br /&gt;    printf("  Strake size %d\n", strake_size);&lt;br /&gt;    printf("  Strakes %d\n", strakes);&lt;br /&gt;    printf("  Last strake size %d\n\n", last_strake_size);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;    // uncomment if you want to using CUDA's elapsed timer&lt;br /&gt;    // float elapsed_time_ms = 0.0f;&lt;br /&gt;    // cudaEvent_t  start, stop;&lt;br /&gt;    // cudaEventCreate( &amp;start);&lt;br /&gt;    // cudaEventCreate( &amp;stop);&lt;br /&gt;    // cudaEventRecord(start, 0);&lt;br /&gt;&lt;br /&gt;    dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);&lt;br /&gt;    dim3 dimGrid(((width*4)/dimBlock.x) + (((width*4)%dimBlock.x)?1:0), BLOCK_SIZE);&lt;br /&gt;&lt;br /&gt;    cudaMalloc((void**)&amp;cuda_image_ptr, strake_size);&lt;br /&gt;    if ((err = cudaGetLastError()) != cudaSuccess) {&lt;br /&gt;        fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));&lt;br /&gt;        exit(2);&lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    for (int i = 0; i &amp;lt; strakes; i++) {&lt;br /&gt;        if (i &amp;gt; 0 &amp;&amp; i == strakes - 1) {&lt;br /&gt;            this_strake_size = last_strake_size;&lt;br /&gt;        } else {&lt;br /&gt;            this_strake_size = strake_size;&lt;br /&gt;        }&lt;br /&gt;        offset = 0 + i *(strake_size/4);&lt;br /&gt;&lt;br /&gt;        cudaMemcpy(cuda_image_ptr, &amp;image[offset], this_strake_size, cudaMemcpyHostToDevice);&lt;br /&gt;        if ((err = cudaGetLastError()) != cudaSuccess) {&lt;br /&gt;            fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));&lt;br /&gt;            exit(2);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // invoke CUDA kernel&lt;br /&gt;        myCudaInvertPixel&amp;lt;&amp;lt;&amp;lt;dimGrid, dimBlock&amp;gt;&amp;gt;&amp;gt;(cuda_image_ptr, width);&lt;br /&gt;        if ((err = cudaGetLastError()) != cudaSuccess) {&lt;br /&gt;           fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));&lt;br /&gt;           exit(2);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // not needed here - cudaThreadSynchronize();&lt;br /&gt;&lt;br /&gt;        cudaMemcpy( &amp;image[offset], cuda_image_ptr, this_strake_size, cudaMemcpyDeviceToHost);&lt;br /&gt;        if ((err = cudaGetLastError()) != cudaSuccess) {&lt;br /&gt;            fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));&lt;br /&gt;            exit(2);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    cudaFree(cuda_image_ptr);&lt;br /&gt;&lt;br /&gt;    // uncomment if you want to using CUDA's elapsed timer&lt;br /&gt;    // cudaEventRecord(stop, 0);&lt;br /&gt;    // cudaEventSynchronize(stop);&lt;br /&gt;    // cudaEventElapsedTime( &amp;elapsed_time_ms, start, stop);&lt;br /&gt;    // printf("Elapsed time per CUDA: %f\n", elapsed_time_ms);&lt;br /&gt;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// CUDA kernel definition - invert pixel&lt;br /&gt;__global__ void myCudaInvertPixel(int *pixel, int width)&lt;br /&gt;{&lt;br /&gt;    int ix = blockIdx.x * blockDim.x + threadIdx.x;&lt;br /&gt;    int iy = blockIdx.y * blockDim.y + threadIdx.y;&lt;br /&gt;    int idx = ix + iy*width;&lt;br /&gt;&lt;br /&gt;    if (ix &amp;lt;= width || iy &amp;gt;= BLOCK_SIZE) return;&lt;br /&gt;&lt;br /&gt;    pixel[idx] = 0x00FFFFFF - pixel[idx];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class Timer {&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        timespec starttime, endtime;&lt;br /&gt;        float elapsed;&lt;br /&gt;&lt;br /&gt;        float difftime(timespec start, timespec end) {&lt;br /&gt;            float temp;&lt;br /&gt;&lt;br /&gt;            temp = (end.tv_sec - start.tv_sec)  +&lt;br /&gt;                   (float) (end.tv_nsec - start.tv_nsec) / 1000000000.0;&lt;br /&gt;&lt;br /&gt;            return temp;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;&lt;br /&gt;        Timer() { elapsed = 0.00; }&lt;br /&gt;&lt;br /&gt;        void reset() { elapsed = 0.00; }&lt;br /&gt;&lt;br /&gt;        void start() {&lt;br /&gt;            elapsed = 0.00;&lt;br /&gt;            clock_gettime(CLOCK_MONOTONIC, &amp;starttime);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void stop() {&lt;br /&gt;            clock_gettime(CLOCK_MONOTONIC, &amp;endtime);&lt;br /&gt;            elapsed = elapsed + difftime(starttime, endtime);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void restart() { clock_gettime(CLOCK_MONOTONIC, &amp;starttime); }&lt;br /&gt;&lt;br /&gt;        void print() { cout &amp;lt;&amp;lt; "Elapsed time: " &amp;lt;&amp;lt; elapsed &amp;lt;&amp;lt; endl; }&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class PPM {&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;&lt;br /&gt;    int width;&lt;br /&gt;    int height;&lt;br /&gt;    int maxColor;&lt;br /&gt;    vector &amp;lt;int&amp;gt; image;&lt;br /&gt;    friend class CCL;&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;&lt;br /&gt;    PPM() {&lt;br /&gt;        width = 0;&lt;br /&gt;        height = 0;&lt;br /&gt;        maxColor = 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    int read(char *filename);&lt;br /&gt;&lt;br /&gt;    int write(char* filename);&lt;br /&gt;&lt;br /&gt;    void printsize() {&lt;br /&gt;       cout &amp;lt;&amp;lt; "Image height: " &amp;lt;&amp;lt; height &amp;lt;&amp;lt; endl;&lt;br /&gt;       cout &amp;lt;&amp;lt; "Image width: " &amp;lt;&amp;lt; width &lt;&amp;lt;&amp;lt; endl;&lt;br /&gt;       cout &amp;lt;&amp;lt; "Image vector size: " &amp;lt;&amp;lt; image.size() &amp;lt;&amp;lt; endl;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void invertpixelNoCuda() {&lt;br /&gt;       for (vector&amp;lt;int&amp;gt;::iterator it = image.begin(); it != image.end(); ++it) {&lt;br /&gt;           *it = 0x00FFFFFF - *it;&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void invertpixelCuda() {&lt;br /&gt;       CCL ccl;&lt;br /&gt;       ccl.cuda_ccl(image, width);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    int getwidth() { return width; }&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;PPM::read(char *filename)&lt;br /&gt;{&lt;br /&gt;    FILE *fp = fopen(filename, "r");&lt;br /&gt;    int rgb, x, y;&lt;br /&gt;    unsigned char red, green, blue;&lt;br /&gt;    char buf[256];&lt;br /&gt;    int *pwidth = &amp;width;&lt;br /&gt;    int *pheight = &amp;height;&lt;br /&gt;&lt;br /&gt;    if (fp== NULL) return 1;&lt;br /&gt;&lt;br /&gt;    do {&lt;br /&gt;        fgets(buf, 256, fp);&lt;br /&gt;    } while(buf[0] == '#');&lt;br /&gt;&lt;br /&gt;    if (buf[0] != 'P' || buf[1] != '6') {&lt;br /&gt;       fclose(fp);&lt;br /&gt;       return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    do {&lt;br /&gt;        fgets(buf, 256, fp);&lt;br /&gt;    } while(buf[0] == '#');&lt;br /&gt;&lt;br /&gt;    sscanf(buf, "%u %u", pwidth, pheight);&lt;br /&gt;    fscanf(fp, "%u\n", &amp;maxColor);&lt;br /&gt;&lt;br /&gt;    image.resize(height*width);&lt;br /&gt;    for (y = 0; y &amp;lt; height ; y++) {&lt;br /&gt;        for (x = 0; x &amp;lt; width; x++) {&lt;br /&gt;            fscanf(fp, "%c%c%c", &amp;red, &amp;green, &amp;blue);&lt;br /&gt;            rgb = ((int)blue &amp; 0x000000ff) &amp;lt;&amp;lt; 16 |&lt;br /&gt;                  ((int)green &amp; 0x000000ff ) &amp;lt;&amp;lt; 8 |&lt;br /&gt;                  ((int)red &amp; 0x000000ff) | 0x00000000;&lt;br /&gt;            image[y*width + x] = rgb;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fclose(fp);&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;PPM::write(char* filename)&lt;br /&gt;{&lt;br /&gt;    FILE *fp;&lt;br /&gt;    int  y, x;&lt;br /&gt;    unsigned char red=0, green=0, blue=0;&lt;br /&gt;    int rgb;&lt;br /&gt;&lt;br /&gt;    if ((fp = fopen(filename, "w")) == NULL) {&lt;br /&gt;        fprintf(stderr, "ERROR: Cannot open output file\n");&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fprintf(fp, "P6\n");&lt;br /&gt;    fprintf(fp, "%d %d\n", width, height);&lt;br /&gt;    fprintf(fp, "255\n");&lt;br /&gt;&lt;br /&gt;    for (y = 0; y &amp;lt; height; y++) {&lt;br /&gt;       for (x = 0; x &amp;lt; width; x++) {&lt;br /&gt;          rgb = image[y*width + x];&lt;br /&gt;          blue = (rgb &amp; 0x00FF0000) &amp;gt;&amp;gt; 16;&lt;br /&gt;          green = (rgb &amp; 0x0000FF00) &amp;gt;&amp;gt; 8;&lt;br /&gt;          red = (rgb &amp; 0x000000FF);&lt;br /&gt;          fprintf(fp, "%c%c%c", red, green, blue);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   fclose(fp);&lt;br /&gt;&lt;br /&gt;   return(0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void&lt;br /&gt;usage(char *name,&lt;br /&gt;      int mode)&lt;br /&gt;{&lt;br /&gt;    cerr &amp;lt;&amp;lt; "Usage: " &amp;lt;&amp;lt; name &amp;lt;&amp;lt; " [-c] [-d] [-g] infile outfile" &amp;lt;&amp;lt; endl;&lt;br /&gt;    exit(mode);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main(int argc,&lt;br /&gt;     char *argv[])&lt;br /&gt;{&lt;br /&gt;    int c;&lt;br /&gt;    int cflag = 0, dflag = 0, gflag = 0;&lt;br /&gt;    PPM ppm;&lt;br /&gt;    Timer timer;&lt;br /&gt;&lt;br /&gt;    if (argc == 1)&lt;br /&gt;        usage(argv[0], 0);&lt;br /&gt;&lt;br /&gt;    opterr = 0;&lt;br /&gt;    while ((c = getopt( argc, argv, "cdgh")) != -1) {&lt;br /&gt;       switch (c) {&lt;br /&gt;          case 'c':&lt;br /&gt;             cflag = 1;&lt;br /&gt;             break;&lt;br /&gt;          case 'd':&lt;br /&gt;             dflag = 1;&lt;br /&gt;             break;&lt;br /&gt;          case 'g':&lt;br /&gt;             gflag = 1;&lt;br /&gt;             break;&lt;br /&gt;          case '?':&lt;br /&gt;          case 'h':&lt;br /&gt;             usage(argv[0], 0);&lt;br /&gt;             break;&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (optind != argc-2) {&lt;br /&gt;        cerr &amp;lt;&amp;lt; "ERROR: An input file and an output file must be specified" &amp;lt;&amp;lt; endl;&lt;br /&gt;        usage(argv[0], 1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (ppm.read(argv[optind++])) {&lt;br /&gt;        cerr &amp;lt;&amp;lt; "ERROR: Failed to read input file" &amp;lt;&amp;lt; endl;&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    timer.start();&lt;br /&gt;&lt;br /&gt;    if (dflag) ppm.printsize();&lt;br /&gt;&lt;br /&gt;    if (cflag) ppm.invertpixelNoCuda();&lt;br /&gt;&lt;br /&gt;    if (gflag) ppm.invertpixelCuda();&lt;br /&gt;&lt;br /&gt;    timer.stop();&lt;br /&gt;&lt;br /&gt;    if (ppm.write(argv[optind])) {&lt;br /&gt;        cerr &amp;lt;&amp;lt; "ERROR: Failed to write output file" &amp;lt;&amp;lt; endl;&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    timer.print();&lt;br /&gt;&lt;br /&gt;    exit(0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Well that is all there is to this application. To compile it you need to have at least the nVidia CUDA 2.3 SDK installed and the latest nVidia graphics card driver.  &lt;br /&gt;&lt;br /&gt;If you are new to CUDA programming, I suggest you download the source code, compile it and play around with it on your own computer.  The man pages for Linux do not work (they are all mixed up) but good up-to-date documentation can be found online at &lt;a href='http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/docs/online/index.html'&gt;nVidia CUDA Library Documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You might also want to play around with the block (&lt;i&gt;dimBlock&lt;/i&gt;) and grid (&lt;i&gt;dimGrid&lt;/i&gt;) dimensions.  nVidia has a useful Microsoft Excel &lt;a href='http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls'&gt;Occupancy Calculator Spreadsheet&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;P.S. I tested the application on images up to a 32000 x 32000 pixels on RHEL5.4 using the CUDA 2.3 SDK and an EVGA GeForce GTX 260 graphics card with 896Mb of memory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-3695172439366777243?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/3695172439366777243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/10/invert-large-image-using-cuda.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3695172439366777243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3695172439366777243'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/10/invert-large-image-using-cuda.html' title='Inverting Large Images Using CUDA'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-8004495510700767058</id><published>2009-10-03T11:11:00.021-04:00</published><updated>2009-10-14T20:40:01.023-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CUDA'/><category scheme='http://www.blogger.com/atom/ns#' term='CCL'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Connected Component Labeling 1</title><content type='html'>&lt;![CDATA[ variable name="fpmuphy" value="1" ]]&gt;&lt;br /&gt;Recently, I became interested in &lt;a href='http://en.wikipedia.org/wiki/Connected_Component_Labeling'&gt;connected component labeling&lt;/a&gt; (CCL) algorithms because of a competition on &lt;a href='http://www.topcoder.com'&gt;TopCoder&lt;/a&gt;. Over the next few weeks I plan to explore various algorithms including parallel algorithms written to take advantage of nVidia GPUs via the &lt;a href='http://www.nvidia.com/object/cuda_home.html'&gt;CUDA&lt;/a&gt; programming model. &lt;br /&gt;&lt;br /&gt;To simply things and enable me to concentrate on the algorithms, all images will be in &lt;a href='http://en.wikipedia.org/wiki/Netpbm_format'&gt;PPM&lt;/a&gt; P6 format and will be loaded into a vector (&lt;i&gt;image&lt;/i&gt;) of integers. The image vector will be processed by the CCL algorithm.  The transformed image vector will then be written out to a PPM P6 file for viewing by an external application such as GIMP.&lt;br /&gt;&lt;br /&gt;Here is an example program which contains a PPM class for reading, writing, inverting, and displaying some information about a PPM file.  An image is read into the image vector with the red, green and blue components stored in specific bits of each integer. It also contains a simple timer class which uses &lt;i&gt;clock_getttime()&lt;/i&gt; to retrieve the monotomic time.&lt;br /&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;fstream&amp;gt;&lt;br /&gt;#include &amp;lt;sstream&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;time.h&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;class Timer {&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        timespec starttime, endtime;&lt;br /&gt;        float elapsed;&lt;br /&gt;&lt;br /&gt;        float difftime(timespec start, timespec end)&lt;br /&gt;        {&lt;br /&gt;            float temp;&lt;br /&gt;&lt;br /&gt;            temp = (end.tv_sec - start.tv_sec)  +&lt;br /&gt;                   (float) (end.tv_nsec - start.tv_nsec) / 1000000000.0;&lt;br /&gt;&lt;br /&gt;            return temp;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;&lt;br /&gt;        Timer() {&lt;br /&gt;            elapsed = 0.00;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void reset() {&lt;br /&gt;            elapsed = 0.00;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void start() {&lt;br /&gt;            elapsed = 0.00;&lt;br /&gt;            clock_gettime(CLOCK_MONOTONIC, &amp;starttime);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void stop() {&lt;br /&gt;            clock_gettime(CLOCK_MONOTONIC, &amp;endtime);&lt;br /&gt;            elapsed = elapsed + difftime(starttime, endtime);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void restart() {&lt;br /&gt;            clock_gettime(CLOCK_MONOTONIC, &amp;starttime);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void print() {&lt;br /&gt;            cout &lt;&lt; "Elapsed time: " &lt;&lt; elapsed &lt;&lt; endl;&lt;br /&gt;        }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class PPM {&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;&lt;br /&gt;    int width;&lt;br /&gt;    int height;&lt;br /&gt;    int maxColor;&lt;br /&gt;    vector &lt;int&gt; image;&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;&lt;br /&gt;    PPM()&lt;br /&gt;    {&lt;br /&gt;        width = 0;&lt;br /&gt;        height = 0;&lt;br /&gt;        maxColor = 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    int readfile(char *filename);&lt;br /&gt;&lt;br /&gt;    int writefile(char* filename);&lt;br /&gt;&lt;br /&gt;    void printsize()&lt;br /&gt;    {&lt;br /&gt;       cout &lt;&lt; "Image height: " &lt;&lt; height &lt;&lt; endl;&lt;br /&gt;       cout &lt;&lt; "Image width: " &lt;&lt; width &lt;&lt; endl;&lt;br /&gt;       cout &lt;&lt; "Image vector size: " &lt;&lt; image.size() &lt;&lt; endl;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void invertpixel()&lt;br /&gt;    {&lt;br /&gt;       for (vector&lt;int&gt;::iterator it = image.begin(); it != image.end(); ++it) {&lt;br /&gt;           *it = 0x00FFFFFF - *it;&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;PPM::readfile(char* filename)&lt;br /&gt;{&lt;br /&gt;    ifstream fin;&lt;br /&gt;    char buf[256];&lt;br /&gt;    unsigned char red, green, blue;&lt;br /&gt;    int i, j, rgb;&lt;br /&gt;&lt;br /&gt;    fin.open(filename);&lt;br /&gt;    if (!fin.is_open()) return 1;&lt;br /&gt;&lt;br /&gt;    fin.getline(buf, 256);&lt;br /&gt;    if (buf[0] != 'P' || buf[1] != '6') {&lt;br /&gt;       fin.close();&lt;br /&gt;       return 1;&lt;br /&gt;    }&lt;br /&gt;    while (fin.peek()=='#') fin.getline(buf, 256);&lt;br /&gt;&lt;br /&gt;    fin &gt;&gt; width &gt;&gt; height &gt;&gt; maxColor;&lt;br /&gt;    fin.getline(buf, 256);                // discard rest of line &lt;br /&gt;&lt;br /&gt;    image.resize(height*width);&lt;br /&gt;    for (i = 0; i &lt; height; i++) {&lt;br /&gt;        for (j = 0; j &lt; width; j++) {&lt;br /&gt;            fin &gt;&gt; red &gt;&gt; green &gt;&gt; blue;&lt;br /&gt;            rgb = ((int)blue &amp; 0x000000ff) &lt;&lt; 16 |&lt;br /&gt;                  ((int)green &amp; 0x000000ff ) &lt;&lt; 8 |&lt;br /&gt;                  ((int)red &amp; 0x000000ff) | 0x00000000;&lt;br /&gt;            image[i * width + j] = rgb;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fin.close();&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;PPM::writefile(char* filename)&lt;br /&gt;{&lt;br /&gt;    ofstream fout;&lt;br /&gt;    stringstream ss;&lt;br /&gt;    unsigned char red, green, blue;&lt;br /&gt;    int i, j, rgb;&lt;br /&gt;&lt;br /&gt;    fout.open(filename);&lt;br /&gt;    if (!fout.is_open()) return 1;&lt;br /&gt;&lt;br /&gt;    fout &lt;&lt; "P6" &lt;&lt; endl;&lt;br /&gt;    ss &lt;&lt; width &lt;&lt; " " &lt;&lt; height;&lt;br /&gt;    fout &lt;&lt; ss.str() &lt;&lt; endl;&lt;br /&gt;    fout &lt;&lt; "255" &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;    for (i = 0; i &lt; height; i++) {&lt;br /&gt;        for (j = 0; j &lt; width; j++) {&lt;br /&gt;            rgb = image[i * width + j];&lt;br /&gt;            red = (rgb &amp; 0x000000FF);&lt;br /&gt;            green = (rgb &amp; 0x0000FF00) &gt;&gt; 8;&lt;br /&gt;            blue = (rgb &amp; 0x00FF0000) &gt;&gt; 16;&lt;br /&gt;            fout &lt;&lt; red &lt;&lt; green &lt;&lt; blue;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fout.close();&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;void&lt;br /&gt;usage(char *name,&lt;br /&gt;      int mode)&lt;br /&gt;{&lt;br /&gt;    cerr &lt;&lt; "Usage: " &lt;&lt; name &lt;&lt; " [-d] infile outfile" &lt;&lt; endl;&lt;br /&gt;    exit(mode);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main(int argc,&lt;br /&gt;     char *argv[])&lt;br /&gt;{&lt;br /&gt;    int c, result = 0;&lt;br /&gt;    int dflag = 0, iflag = 0;&lt;br /&gt;    PPM ppm;&lt;br /&gt;    Timer timer;&lt;br /&gt;&lt;br /&gt;    if (argc == 1)&lt;br /&gt;        usage(argv[0], 0);&lt;br /&gt;&lt;br /&gt;    opterr = 0;&lt;br /&gt;    while ((c = getopt( argc, argv, "di")) != -1) {&lt;br /&gt;       switch (c) {&lt;br /&gt;          case 'd':&lt;br /&gt;             dflag = 1;&lt;br /&gt;             break;&lt;br /&gt;          case 'i':&lt;br /&gt;             iflag = 1;&lt;br /&gt;             break;&lt;br /&gt;          case '?':&lt;br /&gt;          case 'h':&lt;br /&gt;             usage(argv[0], 0);&lt;br /&gt;             break;&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (optind != argc-2) {&lt;br /&gt;        cerr &lt;&lt; "ERROR: An input file and an output file must be specified" &lt;&lt; endl;&lt;br /&gt;        usage(argv[0], 1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    timer.start();&lt;br /&gt;    if (ppm.readfile(argv[optind++])) {&lt;br /&gt;        cerr &lt;&lt; "ERROR: Failed to read input file" &lt;&lt; endl;&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (dflag) ppm.printsize();&lt;br /&gt;&lt;br /&gt;    if (iflag) ppm.invertpixel();&lt;br /&gt;&lt;br /&gt;    if (ppm.writefile(argv[optind])) {&lt;br /&gt;        cerr &lt;&lt; "ERROR: Failed to write output file" &lt;&lt; endl;&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    timer.stop();&lt;br /&gt;    timer.print();&lt;br /&gt;&lt;br /&gt;    exit(0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here is an alternative way of reading and writing an image file using &lt;i&gt;mmap()&lt;/i&gt;&lt;br /&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/mman.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int &lt;br /&gt;PPM::readfile(char *filename)&lt;br /&gt;{&lt;br /&gt;    FILE *fp;&lt;br /&gt;    struct stat statbuf;&lt;br /&gt;    char buf[256];&lt;br /&gt;    int *pwidth = &amp;width;&lt;br /&gt;    int *pheight = &amp;height;&lt;br /&gt;&lt;br /&gt;    if ((fp = fopen(filename, "r")) == NULL) return 1;&lt;br /&gt;&lt;br /&gt;    do {&lt;br /&gt;        fgets(buf, 256, fp);&lt;br /&gt;    } while(buf[0] == '#');&lt;br /&gt;&lt;br /&gt;    if (buf[0] != 'P' || buf[1] != '6') {&lt;br /&gt;       fclose(fp);&lt;br /&gt;       return 1;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    do {&lt;br /&gt;        fgets(buf, 256, fp);&lt;br /&gt;    } while(buf[0] == '#');&lt;br /&gt;&lt;br /&gt;    sscanf(buf, "%u %u", pwidth, pheight);&lt;br /&gt;    fscanf(fp, "%u\n", &amp;maxColor);&lt;br /&gt;&lt;br /&gt;    image.resize(height*width);&lt;br /&gt;    long offset = ftell(fp);&lt;br /&gt;    int fd = fileno(fp);&lt;br /&gt;    fstat(fd, &amp;statbuf);&lt;br /&gt;&lt;br /&gt;    unsigned char* data = (unsigned char*)mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);&lt;br /&gt;    if (data == MAP_FAILED) {&lt;br /&gt;        fprintf(stderr, "ERROR: mmap failed. %s\n", strerror(errno));&lt;br /&gt;        fclose(fp);&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    unsigned char* data_offset = (unsigned char*)(data + offset);&lt;br /&gt;    unsigned char red, green, blue;&lt;br /&gt;    int i = 0, o = 0;&lt;br /&gt;    for (int y = 0; y &lt; height * width; y++) {&lt;br /&gt;        blue = data_offset[i++];&lt;br /&gt;        green = data_offset[i++];&lt;br /&gt;        red = data_offset[i++];&lt;br /&gt;        image[o++] = red &lt;&lt; 16 | green &lt;&lt; 8 | blue;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    munmap(data, statbuf.st_size);&lt;br /&gt;    close(fd);&lt;br /&gt;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;PPM::writefile(char* filename)&lt;br /&gt;{&lt;br /&gt;    unsigned int rgb;&lt;br /&gt;    int result;&lt;br /&gt;&lt;br /&gt;    int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);&lt;br /&gt;    if (fd == -1) {&lt;br /&gt;        fprintf(stderr, "ERROR: Cannot create output file\n");&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    char buf[256];&lt;br /&gt;    sprintf(buf, "P6\n%d %d\n255\n", width, height);&lt;br /&gt;    int bufsize = strlen(buf);&lt;br /&gt;&lt;br /&gt;    int mmap_size = bufsize + (height * width * 3);&lt;br /&gt;    if (((result = lseek(fd, mmap_size - 1, SEEK_SET)) == -1) ||&lt;br /&gt;        ((result = write(fd, "", 1)) == -1)) {&lt;br /&gt;        fprintf(stderr, "ERROR: Cannot write null at end of output file\n");&lt;br /&gt;        close(fd);&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    unsigned char* data = (unsigned char*)mmap(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);&lt;br /&gt;    if (data == MAP_FAILED) {&lt;br /&gt;        fprintf(stderr, "ERROR: mmap failed. %s\n", strerror(errno));&lt;br /&gt;        close(fd);&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    int o = 0;&lt;br /&gt;    for (int i = 0; i &lt; bufsize; i++)&lt;br /&gt;        data[o++] = buf[i];&lt;br /&gt;&lt;br /&gt;    for (int i = 0; i &lt; height * width; i++) {&lt;br /&gt;        rgb = image[i];&lt;br /&gt;        data[o++] = rgb &amp; 0xFF;&lt;br /&gt;        data[o++] = (rgb &gt;&gt; 8) &amp; 0xFF;&lt;br /&gt;        data[o++] = (rgb &gt;&gt; 16) &amp; 0xFF;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    munmap(data, mmap_size);&lt;br /&gt;    close(fd);&lt;br /&gt;&lt;br /&gt;    return(0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Note the need to seek to the end of the new file and write a null before calling &lt;i&gt;mmap()&lt;/i&gt; when writing a file. Also MAP_SHARED must be used instead of MAP_PRIVATE otherwise your file will contain nothing but zeros.&lt;br /&gt;&lt;br /&gt;Well, that is all I have time for at present. In my next post on this subject I will implement a 4-connected thresholding union-find algorithm. &lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-8004495510700767058?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/8004495510700767058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/10/connected-component-labeling-algorithms.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8004495510700767058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8004495510700767058'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/10/connected-component-labeling-algorithms.html' title='Connected Component Labeling 1'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-1466552495936836696</id><published>2009-09-19T09:37:00.006-04:00</published><updated>2009-09-19T10:32:06.075-04:00</updated><title type='text'>Coming Soon - Software Engineering PE</title><content type='html'>In August 2009 the &lt;a href='http://www.ncees.org'&gt;NCEES&lt;/a&gt; Board of Directors approved moving forward with the development of a Principles and Practice of Engineering examination, commonly known as the PE (Professional Engineer) exam, for the discipline of software engineering. &lt;br /&gt;&lt;br /&gt;NCEES is the umbrella organization for the engineering and surveying jurisdictional licensing boards in the United States. It develops and administers examinations used for engineering licensure. The prerequisite for NCEES to consider initiating a PE examination in a new discipline includes written requests from no fewer than 10 state licensing boards that can demonstrate a need for the examination in their jurisdictions. The requests must include proof of such need, estimate of usage, and evidence that knowledge areas and skills are not adequately measured in an existing examination. &lt;br /&gt;&lt;br /&gt;In addition, no new discipline can be added to the examination program unless there is an &lt;a href='http://www.abet.org'&gt;ABET&lt;/a&gt;-accredited degree in that discipline. The jurisdictional licensing boards requesting the examination were those with significant amounts of software engineering industry and those that have institutions granting ABET-accredited degrees in software engineering. &lt;br /&gt;&lt;br /&gt;Over the past decade there have been several efforts to establish a path to professional practice licensure for software engineers in the United States. These efforts failed for various reasons. The main obstacle was the lack of a reasonable number of ABET-accredited programs offering an undergraduate degree in software engineering. This is no longer tha case as there are now a number of ABET-accredited software engineering undergraduate degree programs available in the United States. &lt;br /&gt;&lt;br /&gt;In a report from the &lt;a href='http://www.ieeeusa.org/volunteers/committees/lrc/'&gt;IEEE-USA Licensure and Registration&lt;/a&gt; committee, it was noted that software engineering professional licensure affects both US IEEE members and society at large. The central issue is one of protection of public safety, health and welfare, since the purpose of licensure is to establish competence to practice in an area and not to measure the level of an individual’s expertise above the competency threshold.  A large number of technologies in existence today are directly impacted by software engineering, including safety critical artifacts such as real-time controllers and logistics systems. In addition other countries such as Canada require licensing of software engineers.&lt;br /&gt;&lt;br /&gt;In July 2007, a group of stakeholder organizations including members of NSPE (National Society of Professional Engineers), &lt;a 'http://www.ieee.org'&gt;IEEE&lt;/a&gt;, and TBPE (Texas Board of Professional Engineers) established the Software Engineering  Licensure Consortium (SELC.) SELC developed a software engineering licensure needs document that was distributed to licensing boards. It also conducted a survey to determine need and interest in establishing a software engineering licensure path. &lt;br /&gt;&lt;br /&gt;What comes next? The next phase is known as a Professional Activities and Knowledge Study (PAKS). The PAKS process will include the development of surveys and meetings with licensed engineers who practice software engineering that will ultimately result in a specification of the content for the software engineering licensure examination. Once the specification is developed, a committee of software engineers is formed to develop examination questions under the oversight of NCEES. After NCEES receives and approves the committee’s software engineering PE examination, it will be each up to individual licensing boards whether they license software engineers in their state or territory.&lt;br /&gt;&lt;br /&gt;Professional licensure for an engineering discipline is established by each U.S. jurisdiction at their discretion. The existence of the software engineering PE examination does not automatically mean that each jurisdiction will approve a software engineer license since each board makes such a decision based on the needs (and politics) of their individual jurisdictions.&lt;br /&gt;&lt;br /&gt;Hopefully the PAKS process will only take a year or two and the resulting examination will be approved by NCEES without delay.  Meanwhile software engineers should start canvasing their state engineering licensing boards to approve licenses in this discipline once the software engineering PE examination is available.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-1466552495936836696?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/1466552495936836696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/09/coming-soon-pe-software-engineering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1466552495936836696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1466552495936836696'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/09/coming-soon-pe-software-engineering.html' title='Coming Soon - Software Engineering PE'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-6743235636847197844</id><published>2009-09-14T11:06:00.009-04:00</published><updated>2009-12-07T18:31:40.059-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Plymouth'/><title type='text'>Project Plymouth</title><content type='html'>&lt;a href='http://www.freedesktop.org/wiki/Software/Plymouth'&gt;Plymouth&lt;/a&gt; is the codename for a &lt;a href='http://www.freedesktop.org'&gt;freedesktop.org&lt;/a&gt; project started in 2007 by Ray Strobe of &lt;a href='http://www.redhat.com'&gt;Redhat&lt;/a&gt; to develop a graphical application to display a flicker free animated splash screen during the boot process while logging console text output to a log file.  Fedora 10 (&lt;em&gt;Cambridge&lt;/em&gt;) was the first release of Fedora to contain Plymouth.  Development work is actively ongoing and the current release is 0.71. &lt;br /&gt;&lt;br /&gt;Plymouth is intended to be a replacement for &lt;em&gt;rhgb&lt;/em&gt; (Red Hat Graphical Boot) which is currently used by Red Hat to provide a graphical boot display.   If &lt;em&gt;rhgb&lt;/em&gt; is part of the kernel command line, &lt;em&gt;rhgb&lt;/em&gt; is started early in the boot process by &lt;em&gt;/etc/sysinit&lt;/em&gt;.  &lt;em&gt;rhgb&lt;/em&gt; starts an X server for display :1 on one virtual terminal so that it avoids conflict with the regular X server which may be starting for display :0 on another virtual terminal. It also creates a Unix domain socket (&lt;em&gt;/etc/rhgb/temp/rhgb-socket&lt;/em&gt;) so that boot scripts can communicate with it.  As boot scripts execute, they can use &lt;em&gt;rhgb-client&lt;/em&gt; to send messages to &lt;em&gt;rhgb&lt;/em&gt;, which then updates the text and progress display.  When the system is finished booting, &lt;em&gt;rhgb-client&lt;/em&gt; is invoked with the &lt;em&gt;--quit&lt;/em&gt; option to send a terminate request to &lt;em&gt;rhgb&lt;/em&gt;.  The user is then switched to the X server used by the display manager.  Unfortunately the sequence of switching from text mode to &lt;em&gt;rhgb&lt;/em&gt;'s X server to text mode to the display manager's X server can cause significant screen flickering.  Another major drawback of &lt;em&gt;rhgb&lt;/em&gt; is that boot messages are not logged. &lt;br /&gt;&lt;br /&gt;Plymouth is designed to work on systems with DRM (Direct Rendering Manager) kernel modesetting drivers.  DRM is a component of the &lt;a href='http://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure'&gt;Direct Rendering Infrastructure&lt;/a&gt; project.  It consists of two kernel modules, a generic DRM driver, and another which has support for the specific graphics card hardware. This pair of drivers allows a userspace client direct access to the graphics card hardware.  See &lt;a href=' http://dri.freedesktop.org/wiki/DrmModesetting'&gt;here&lt;/a&gt; for further information on DRM mode setting.  The idea behind Plymouth is that very early on in the boot process the native video display mode for the system is set by a kernel mode setting driver.  In turn Plymouth uses that mode, and that mode remains the same during the entire boot process up to and after an X server starts.  For systems without kernel modesetting drivers, there is a fallback text mode which is the familiar tricolor blue/white/black progress bar.  Plymouth also drops back to this text mode if the default plugin fails for whatever reason.  &lt;br /&gt; &lt;br /&gt;Kernel modesetting drivers are still in active development and somewhat buggy.  Currently, only Radeon R500 and higher series graphics cards support kernel modesetting by default. There is work in progress to provide kernel modesetting support for R100 and R200 graphics cards.  Intel kernel modesetting drivers exist but are not turned on by default.  Support for kernel modesetting in the nVidia graphic cards via the Nouveau driver is still experimental.   If you end up with nothing but a black screen during boot up, or a screen with nothing but random noise on it, try adding &lt;em&gt;nomodeset&lt;/em&gt; to the kernel command line to disable kernel mode setting. &lt;br /&gt; &lt;br /&gt;If there is no suitable kernel modesetting driver available for your particular graphics card or you want to set an explicit mode, you can add the string &lt;em&gt;vga=XXX&lt;/em&gt; to the kernel command line.  The kernel command line option  &lt;em&gt;vga=ask&lt;/em&gt;  invokes the the built-in &lt;em&gt;vesa&lt;/em&gt; framebuffer driver, displays a list of supported modes and asks you to select a mode.  It then boots the kernel using this mode.  The kernel command line option &lt;em&gt;vga=mode&lt;/em&gt;, where &lt;em&gt;mode&lt;/em&gt; is either a 4 digit hexadecimal with a leading zero and no letter 'x' or a 3 digit decimal number, enables you to set a specific mode.  &lt;br /&gt;&lt;br /&gt;How can you tell what particular modes are available and which will work best for you?  This really depends on the type of graphics card that you have in your system, and the amount of video memory available.  The only way is to experiment with different modes.&lt;br /&gt;&lt;br /&gt;The following table shows the mode numbers you can input at the &lt;em&gt;vga=&lt;/em&gt; prompt using hexadecimals&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sq5cSfkfbSI/AAAAAAAAAHM/BirpkOREFnc/s1600-h/VGA1.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 640px; height: 100px;" src="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sq5cSfkfbSI/AAAAAAAAAHM/BirpkOREFnc/s320/VGA1.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5381340077536275746" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;and here is the same table using decimal numbers.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sq5cYK-EsnI/AAAAAAAAAHU/_X81eJA3xg4/s1600-h/VGA2.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 640px; height: 100px;" src="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sq5cYK-EsnI/AAAAAAAAAHU/_X81eJA3xg4/s320/VGA2.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5381340175085646450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that  8 bits = 256 colors, 15 bits [5:5:5] = 32,768 colors, 16 bits [5:6:5] = 65,536 colors and 24 bits [8:8:8] = 16.8 million colors.  Additional modes are at the discretion of the graphics card manufacturer, as the VESA 2.0 specification only defines modes up to 0x31F.  For more information about VESA modes, see this article about &lt;a href='http://en.wikipedia.org/wiki/VESA_BIOS_Extensions'&gt;VESA BIOS Extension&lt;/a&gt; compliant graphic cards. &lt;br /&gt;&lt;br /&gt;Plymouth works with themes which are analogous to screensavers that are displayed at boot time.  Fedora 11 shipped with three graphical themes &lt;em&gt;solar&lt;/em&gt;, &lt;em&gt;fade-in&lt;/em&gt; and &lt;em&gt;spinfinity&lt;/em&gt;, and two non-graphical themes &lt;em&gt;text&lt;/em&gt; and &lt;em&gt;details&lt;/em&gt;.  The &lt;em&gt;text&lt;/em&gt; theme is the default theme which is displayed if another theme fails for whatever reason.&lt;br /&gt;&lt;br /&gt;The terminology and technology around themes and plugins has evolved as the project progressed.  The version of Plymouth that shipped in Fedora 10 was based on a plugin system where each splash screen had to be coded from scratch. This problem was recognized and for Fedora 11 Plymouth went through a major rewrite whereby it now supports themes which in turn use standard plugins.  Thus theme developers can now focus on the theme graphics rather than having to do raw coding.&lt;br /&gt;&lt;br /&gt;Currently there are five themes in the Fedora repositories.  &lt;a href='https://fedoraproject.org/w/uploads/5/5f/Plymouth-charge.ogg'&gt;Charge&lt;/a&gt; is the default theme for Fedora 11 (Leonidas). &lt;em&gt;Spinfinity&lt;/em&gt; is a throbber that moves in a path shaped like the infinity sign. &lt;em&gt;Fade-In&lt;/em&gt; shows the Fedora logo fading in and out in a star field.  &lt;em&gt;details&lt;/em&gt; shows the classic scrolling output from the boot process. &lt;em&gt;text&lt;/em&gt; is the fallback bottom of the screen tricolor theme.  &lt;em&gt;Solar&lt;/em&gt;, my personal favorite to date and the default theme for Fedora 10, was not included in Fedora 11.  It displays a planet with exploding pulsars. &lt;br /&gt;&lt;br /&gt;To install all the Plymouth themes in the Fedora repositories:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;# yum -y install plymouth-theme-*&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Installed Plymouth themes can be listed use the &lt;em&gt;plymouth-set-default-theme&lt;/em&gt; script:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;# /usr/sbin/plymouth-set-default-theme --list&lt;br /&gt;charge&lt;br /&gt;details&lt;br /&gt;fade-in&lt;br /&gt;spinfinity&lt;br /&gt;text&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Theme files are stored in the &lt;em&gt;/usr/share/plymouth/themes&lt;/em&gt; subdirectory.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;# ls /usr/share/plymouth/themes/&lt;br /&gt;charge  default.plymouth  details  fade-in  spinfinity  text&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Note that &lt;em&gt;default.plymouth&lt;/em&gt; is a symbolic link to the actual designed default theme.&lt;br /&gt;&lt;br /&gt;There are two types of plugins: &lt;em&gt;splash&lt;/em&gt; and &lt;em&gt;control&lt;/em&gt;.  There can only be one splash plugin in use at a time.  A splash plugin is what draws the splash screen, asks for a password, displays messages, and more.  A theme calls a splash plugin to do the actual work.  For example, here is a listing of the files associated with the &lt;em&gt;charge&lt;/em&gt; theme.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ ls /usr/share/plymouth/themes/charge&lt;br /&gt;box.png          progress-01.png  progress-07.png  progress-13.png  throbber-00.png  throbber-06.png  throbber-12.png&lt;br /&gt;bullet.png       progress-02.png  progress-08.png  progress-14.png  throbber-01.png  throbber-07.png  throbber-13.png&lt;br /&gt;charge.plymouth  progress-03.png  progress-09.png  progress-15.png  throbber-02.png  throbber-08.png  throbber-14.png&lt;br /&gt;entry.png        progress-04.png  progress-10.png  progress-16.png  throbber-03.png  throbber-09.png  throbber-15.png&lt;br /&gt;lock.png         progress-05.png  progress-11.png  progress-17.png  throbber-04.png  throbber-10.png&lt;br /&gt;progress-00.png  progress-06.png  progress-12.png  progress-18.png  throbber-05.png  throbber-11.png&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The theme configuration file that is read by &lt;em&gt;plymouthd&lt;/em&gt; is the name of the theme with a &lt;em&gt;.plymouth&lt;/em&gt; extension.  In this case it is &lt;em&gt;charge.plymouth&lt;/em&gt;.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ cat /usr/share/plymouth/themes/charge/charge.plymouth&lt;br /&gt;[Plymouth Theme]&lt;br /&gt;Name=Charge&lt;br /&gt;Description=A theme that features the shadowy hull of a Fedora logo charge up and and finally burst into into full form.&lt;br /&gt;ModuleName=two-step&lt;br /&gt;&lt;br /&gt;[two-step]&lt;br /&gt;ImageDir=/usr/share/plymouth/themes/charge&lt;br /&gt;HorizontalAlignment=.5&lt;br /&gt;VerticalAlignment=.5&lt;br /&gt;Transition=none&lt;br /&gt;TransitionDuration=0.0&lt;br /&gt;BackgroundStartColor=0x416fa7&lt;br /&gt;BackgroundEndColor=0x4b83c1&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;This theme calls the &lt;em&gt;two-step&lt;/em&gt; plugin to do the actual work of displaying the theme.  The &lt;em&gt;two-step&lt;/em&gt; plugin expects a certain number and type of image files with specific names.  Various directives can be passed to plugins; the number and type being plugin specific.  For example different type of transitions can be specified for the &lt;em&gt;two-step&lt;/em&gt; plugin using the &lt;em&gt;Transition&lt;/em&gt; directive, i.e. &lt;em&gt;fade-over&lt;/em&gt;, &lt;em&gt;cross-fade&lt;/em&gt; and &lt;em&gt;merge-fade&lt;/em&gt;.  &lt;br /&gt;&lt;br /&gt;Some plugins did not ship with Fedora 11.  One such plugin is the &lt;em&gt;label&lt;/em&gt; plugin.  It is not part of &lt;em&gt;initrd&lt;/em&gt; but is loadable once the root filesystem is mounted.  It is implicitly loaded when a splash plugin attempts to display text.  After &lt;em&gt;label&lt;/em&gt; is loaded, it uses &lt;a href='http://www.pango.org'&gt;pango&lt;/a&gt; and &lt;a href='http://cairographics.org'&gt;cairo&lt;/a&gt; to handle message localization.  &lt;br /&gt;&lt;br /&gt;Another such plugin is &lt;em&gt;script&lt;/em&gt; which supports a &lt;a  href='http://www.freedesktop.org/wiki/Software/Plymouth/Scripts'&gt;scripting language&lt;/a&gt; for themes.  It supports two basic objects, i.e. Image and Sprite.  If you are familiar with Javascript or the C language you should be comfortable with the syntax and idiom.  Note that the scripting language is undergoing rapid development at present with a view to making it more object orientated so you may have to read the git logs or the source code to figure out what is or is not supported.&lt;br /&gt;&lt;br /&gt;For examples of scripted themes, I recommend you look at the sources for the &lt;a href='http://www.cs.man.ac.uk/~brejc8/temp/vizta.tar.gz'&gt;Vizta&lt;/a&gt; or the &lt;a href='http://www.cs.man.ac.uk/~brejc8/temp/dandelion.tar.gz'&gt;Dandelion&lt;/a&gt; themes.  These themes were both developed by Charlie Brie, a research assistant at the University of Manchester UK,  who is the main developer behind the scripting language.  If you want to try these themes out on Fedora 11, you will have to import the sources from the Plymouth Git tree, configure, rebuild and install on your system.&lt;br /&gt;&lt;br /&gt;The two main binaries involved in Plymouth are &lt;em&gt;/sbin/plymouthd&lt;/em&gt;, a daemon that does most of the actual work by displaying the splash screen and logging the boot session, and  &lt;em&gt;/bin/plymouth&lt;/em&gt; which is the interface to &lt;em&gt;/sbin/plymouthd&lt;/em&gt;. Unfortunately no man page is supplied for &lt;em&gt;/bin/plymouth&lt;/em&gt; but there is some information in the &lt;em&gt;/usr/share/doc/plymouth-0.7.0&lt;/em&gt; subdirectory.  Both have a number of useful options.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ /sbin/plymouthd --help&lt;br /&gt;Boot splash control server&lt;br /&gt;USAGE: plymouthd [OPTION...]&lt;br /&gt;Options:&lt;br /&gt;  --help                 This help message&lt;br /&gt;  --attach-to-session    Redirect console messages from screen to log&lt;br /&gt;  --no-daemon            Do not daemonize&lt;br /&gt;  --debug                Output debugging information&lt;br /&gt;  --mode=&lt;string&gt;        Mode is one of: boot, shutdown&lt;br /&gt;&lt;br /&gt;$ /bin/plymouth --help&lt;br /&gt;Boot splash control client&lt;br /&gt;USAGE: plymouth [OPTION...] [COMMAND [OPTION...]...]&lt;br /&gt;&lt;br /&gt;Options:&lt;br /&gt;  --help                         This help message&lt;br /&gt;  --debug                        Enable verbose debug logging&lt;br /&gt;  --newroot=&lt;string&gt;             Tell boot daemon that new root filesystem is mounted&lt;br /&gt;  --quit                         Tell boot daemon to quit&lt;br /&gt;  --ping                         Check of boot daemon is running&lt;br /&gt;  --sysinit                      Tell boot daemon root filesystem is mounted read-write&lt;br /&gt;  --show-splash                  Show splash screen&lt;br /&gt;  --hide-splash                  Hide splash screen&lt;br /&gt;  --ask-for-password             Ask user for password&lt;br /&gt;  --ignore-keystroke=&lt;string&gt;    Remove sensitivity to a keystroke&lt;br /&gt;  --update=&lt;string&gt;              Tell boot daemon an update about boot progress&lt;br /&gt;  --details                      Tell boot daemon there were errors during boot&lt;br /&gt;  --wait                         Wait for boot daemon to quit&lt;br /&gt;&lt;br /&gt;Available commands:&lt;br /&gt;  ask-for-password   Ask user for password&lt;br /&gt;  ask-question       Ask user a question&lt;br /&gt;  message            Display a message&lt;br /&gt;  watch-keystroke    Become sensitive to a keystroke&lt;br /&gt;  pause-progress     Pause boot progress bar&lt;br /&gt;  unpause-progress   Unpause boot progress bar&lt;br /&gt;  report-error       Tell boot daemon there were errors during boot&lt;br /&gt;  quit               Tell boot daemon to quit&lt;br /&gt;&lt;br /&gt;Options for ask-for-password command:&lt;br /&gt;  --command=&lt;string&gt;             Command to send password to via standard input&lt;br /&gt;  --prompt=&lt;string&gt;              Message to display when asking for password&lt;br /&gt;  --number-of-tries=&lt;integer&gt;    Number of times to ask before giving up (requires --command)&lt;br /&gt;  --dont-pause-progress          Don't pause boot progress bar while asking&lt;br /&gt;&lt;br /&gt;Options for ask-question command:&lt;br /&gt;  --command=&lt;string&gt;       Command to send the answer to via standard input&lt;br /&gt;  --prompt=&lt;string&gt;        Message to display when asking the question&lt;br /&gt;  --dont-pause-progress    Don't pause boot progress bar while asking&lt;br /&gt;&lt;br /&gt;Options for message command:&lt;br /&gt;  --text=&lt;string&gt;    The message text&lt;br /&gt;&lt;br /&gt;Options for watch-keystroke command:&lt;br /&gt;  --command=&lt;string&gt;    Command to send keystroke to via standard input&lt;br /&gt;  --keys=&lt;string&gt;       Keys to become sensitive to&lt;br /&gt;&lt;br /&gt;Options for quit command:&lt;br /&gt;  --retain-splash    Don't explicitly hide boot splash on exit&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;In Fedora &lt;em&gt;/usr/bin/rhgb-client&lt;/em&gt;  is a symbolic link to &lt;em&gt;/usr/bin/plymouth&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;One way to experiment with Plymouth is to invoke it from runlevel 2 or 3.  For example, here is a simple script to display the default theme for 5 seconds, ask for a password, and ask for your name before finally quitting.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;&lt;br /&gt;# first check that we are in an appropriate runlevel&lt;br /&gt;rlevel=$(runlevel | cut -d " " -f 2)&lt;br /&gt;if [[ "$rlevel" != "2"  &amp;&amp; "$rlevel" != "3" ]]&lt;br /&gt;then&lt;br /&gt;    echo "ERROR: You must be at runlevel 2 or 3"&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;echo "Testing plymouth default theme ..."&lt;br /&gt;plymouthd&lt;br /&gt;sleep 1&lt;br /&gt;&lt;br /&gt;# check if the plymouthd daemon is alive&lt;br /&gt;plymouth --ping&lt;br /&gt;if [[ $? -eq 1 ]]&lt;br /&gt;then&lt;br /&gt;    echo "ERROR: Plymouth daemon not running"&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;# show the default splash screen for 5 seconds&lt;br /&gt;plymouth  --show-splash&lt;br /&gt;sleep 5&lt;br /&gt;&lt;br /&gt;plymouth --ask-for-password&lt;br /&gt;sleep 2&lt;br /&gt;&lt;br /&gt;# using a command rather than an option&lt;br /&gt;plymouth ask-question --prompt="What is your name?"&lt;br /&gt;sleep 5&lt;br /&gt;&lt;br /&gt;plymouth --quit&lt;br /&gt;&lt;br /&gt;echo "Done ..."&lt;br /&gt;exit 0&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Note that not all plugins support every command and option at the present time.  The above script works with the &lt;em&gt;solar&lt;/em&gt; theme which uses the &lt;em&gt;space-flares&lt;/em&gt; plugin.  However this plugin does not support the message command for example.  A useful option which is missing from &lt;em&gt;plymouth&lt;/em&gt; would be an option to enumerate which commands were supported.&lt;br /&gt;&lt;br /&gt;Plymouth is not really designed to be built from source by end users. For it to work correctly, it has to be integrated into the underlying  distribution. Because it starts so early in the boot process, it needs to be added to a distribution's &lt;a href='http://en.wikipedia.org/wiki/Initrd'&gt;initrd&lt;/a&gt; (initial ram disk) and the distribution needs to interface with &lt;em&gt;plymouthd&lt;/em&gt; to tell it how the boot is progressing.  For example, here is the &lt;em&gt;nash&lt;/em&gt; script  in my Fedora 11 &lt;em&gt;initrd&lt;/em&gt;.   Notice how the Plymouth splash screen is called as soon as a console is available and also several other times in the script.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;lsinitrd /boot/initrd-2.6.29.5-191.fc11.x86_64.img&lt;br /&gt;.........................&lt;br /&gt;#!/bin/nash&lt;br /&gt;mount -t proc /proc /proc&lt;br /&gt;setquiet&lt;br /&gt;echo Mounting proc filesystem&lt;br /&gt;echo Mounting sysfs filesystem&lt;br /&gt;mount -t sysfs /sys /sys&lt;br /&gt;echo Creating /dev&lt;br /&gt;mount -o mode=0755 -t tmpfs /dev /dev&lt;br /&gt;mkdir /dev/pts&lt;br /&gt;mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts&lt;br /&gt;mkdir /dev/shm&lt;br /&gt;mkdir /dev/mapper&lt;br /&gt;echo Creating initial device nodes&lt;br /&gt;mknod /dev/null c 1 3&lt;br /&gt;mknod /dev/zero c 1 5&lt;br /&gt;mknod /dev/systty c 4 0&lt;br /&gt;mknod /dev/tty c 5 0&lt;br /&gt;mknod /dev/console c 5 1&lt;br /&gt;mknod /dev/ptmx c 5 2&lt;br /&gt;mknod /dev/fb c 29 0&lt;br /&gt;mknod /dev/hvc0 c 229 0&lt;br /&gt;mknod /dev/tty0 c 4 0&lt;br /&gt;mknod /dev/tty1 c 4 1&lt;br /&gt;mknod /dev/tty2 c 4 2&lt;br /&gt;mknod /dev/tty3 c 4 3&lt;br /&gt;mknod /dev/tty4 c 4 4&lt;br /&gt;mknod /dev/tty5 c 4 5&lt;br /&gt;mknod /dev/tty6 c 4 6&lt;br /&gt;mknod /dev/tty7 c 4 7&lt;br /&gt;mknod /dev/tty8 c 4 8&lt;br /&gt;mknod /dev/tty9 c 4 9&lt;br /&gt;mknod /dev/tty10 c 4 10&lt;br /&gt;mknod /dev/tty11 c 4 11&lt;br /&gt;mknod /dev/tty12 c 4 12&lt;br /&gt;mknod /dev/ttyS0 c 4 64&lt;br /&gt;mknod /dev/ttyS1 c 4 65&lt;br /&gt;mknod /dev/ttyS2 c 4 66&lt;br /&gt;mknod /dev/ttyS3 c 4 67&lt;br /&gt;daemonize --ignore-missing /bin/plymouthd&lt;br /&gt;/lib/udev/console_init tty0&lt;br /&gt;plymouth --show-splash&lt;br /&gt;echo Setting up hotplug.&lt;br /&gt;hotplug&lt;br /&gt;echo Creating block device nodes.&lt;br /&gt;mkblkdevs&lt;br /&gt;echo Creating character device nodes.&lt;br /&gt;mkchardevs&lt;br /&gt;echo Making device-mapper control node&lt;br /&gt;mkdmnod&lt;br /&gt;modprobe scsi_wait_scan&lt;br /&gt;rmmod scsi_wait_scan&lt;br /&gt;mkblkdevs&lt;br /&gt;echo Scanning logical volumes&lt;br /&gt;lvm vgscan --ignorelockingfailure&lt;br /&gt;echo Activating logical volumes&lt;br /&gt;lvm vgchange -ay --ignorelockingfailure  vg_ultra&lt;br /&gt;resume /dev/mapper/vg_ultra-lv_swap&lt;br /&gt;echo Creating root device.&lt;br /&gt;mkrootdev -t ext4 -o defaults,ro /dev/mapper/vg_ultra-lv_root&lt;br /&gt;echo Mounting root filesystem.&lt;br /&gt;mount /sysroot&lt;br /&gt;cond -ne 0 plymouth --hide-splash&lt;br /&gt;echo Setting up other filesystems.&lt;br /&gt;setuproot&lt;br /&gt;loadpolicy&lt;br /&gt;plymouth --newroot=/sysroot&lt;br /&gt;echo Switching to new root and running init.&lt;br /&gt;switchroot&lt;br /&gt;echo Booting has failed.&lt;br /&gt;sleep -1&lt;br /&gt;init&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;During the boot progress the boot status is regularly updated with strings signifying what is happening.  Plugins can listen to these if they choose to but they are generally ignored in the current plugins, and are only used for calculating the boot time estimation. In Fedora 11, For example the &lt;em&gt;rc.sysinit&lt;/em&gt; script includes several calls to &lt;em&gt;plymouth&lt;/em&gt; to hide or show the splash screen according to whether a password is needed to access a filesystem or a filesystem is to be relabeled by selinux.&lt;br /&gt;&lt;br /&gt;So how does Plymouth know when to quit?  Actually, it has no way of knowing.  It just keeps on going until it receives a quit message.  In the case of Fedora 11, the &lt;em&gt;/etc/event.d/quit-plymouth&lt;/em&gt; script sends the quit message.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;# quit-plymouth - script to stop boot splash&lt;br /&gt;#&lt;br /&gt;# This service triggers plymouth to quit when we reach the&lt;br /&gt;# end of the boot cycle. We start on 'stopping rcX' to make sure&lt;br /&gt;# this completes before the getty starts.&lt;br /&gt;# prefdm handles quit differently, though.&lt;br /&gt;&lt;br /&gt;start on runlevel S&lt;br /&gt;start on stopping rc2&lt;br /&gt;start on stopping rc3&lt;br /&gt;start on stopping rc4&lt;br /&gt;&lt;br /&gt;script&lt;br /&gt;         /usr/bin/plymouth quit || :&lt;br /&gt;end script&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;A special case is when a user boots to single user.  In this case the /etc/event.d/rcS-sulogin script is executed.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;# rcS-sulogin - "single-user" runlevel compatibility&lt;br /&gt;#&lt;br /&gt;# This task runs /bin/bash during "single-user" mode,&lt;br /&gt;# then continues to the default runlevel.&lt;br /&gt;&lt;br /&gt;start on runlevel S&lt;br /&gt;&lt;br /&gt;stop on runlevel&lt;br /&gt;&lt;br /&gt;console owner&lt;br /&gt;script&lt;br /&gt;        runlevel --set S &gt;/dev/null || true&lt;br /&gt;        plymouth --hide-splash || true&lt;br /&gt;        exec /bin/bash&lt;br /&gt;end script&lt;br /&gt;post-stop script&lt;br /&gt;        if [ "$1" = "S" ]; then&lt;br /&gt;                runlevel=$(/bin/awk -F ':' '$3 == "initdefault" &amp;&amp; $1 !~ "^#" { print $2 }' /etc/inittab)&lt;br /&gt;                [ -z "$runlevel" ] &amp;&amp; runlevel="3"&lt;br /&gt;                exec telinit $runlevel&lt;br /&gt;        fi&lt;br /&gt;end script&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;What is not commonly known is that you can also use Plymouth to provide a splash screen during system shutdown or reboot.  This is done in Fedora 11 via the &lt;em&gt;/etc/event.d/plymouth-shutdown&lt;/em&gt; script. as shown below.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;# plymouth-shutdown - put up shutdown splash&lt;br /&gt;#&lt;br /&gt;# This service triggers plymouth to put up a splash&lt;br /&gt;# when leaving runlevel 5.&lt;br /&gt;&lt;br /&gt;start on stopped prefdm&lt;br /&gt;&lt;br /&gt;console output&lt;br /&gt;script&lt;br /&gt;        set $(runlevel || true)&lt;br /&gt;        if [ "$2" != "0" ] &amp;&amp; [ "$2" != "6" ]; then&lt;br /&gt;                exit 0&lt;br /&gt;        fi&lt;br /&gt;&lt;br /&gt;        /sbin/plymouthd --mode=shutdown || exit 1&lt;br /&gt;        /bin/plymouth --sysinit&lt;br /&gt;        /bin/plymouth --show-splash&lt;br /&gt;        if [ "$2" = "0" ]; then&lt;br /&gt;                /bin/plymouth message --text="Shutting down..."&lt;br /&gt;        elif [ "$2" = "6" ]; then&lt;br /&gt;                /bin/plymouth message --text="Restarting..."&lt;br /&gt;        fi&lt;br /&gt;end script&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Console boot messages are redirected to a pseudo-terminal which is created very early on in the boot process.  These messages are buffered until filesystems are fully mounted. Then the buffer is dumped to &lt;em&gt;/var/log/boot.&lt;/em&gt;.  In either text or graphics mode, the boot messages are obscured.  However you can see these messages at any time during boot sequence by hitting the &lt;em&gt;ESC&lt;/em&gt; key. &lt;br /&gt;&lt;br /&gt;One of the side effects of changing Plymouth themes is that you have to generate a new &lt;em&gt;initrd&lt;/em&gt; image.  Usually this is done using the &lt;em&gt;mkinird&lt;/em&gt; script.  However there is an alternative to doing this.  You can modify your existing &lt;em&gt;initrd&lt;/em&gt; image to remove any Plymouth-related files and create a second &lt;em&gt;initrd&lt;/em&gt; image which contains just the Plymouth-related files.  When you change a theme, only the Plymouth image needs to be generated.  You have to modify &lt;em&gt;grub.conf&lt;/em&gt; to load both images when booting.  Here is a stanza from my &lt;em&gt;grub.conf&lt;/em&gt; which does just that.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;title Graphical Boot (Fedora 2.6.29.6-217.2.16.fc11.x86_64)&lt;br /&gt;        root (hd0,1)&lt;br /&gt;        kernel /vmlinuz-2.6.30.5-43.fc11.x86_64 ro root=/dev/mapper/vg_ultra-lv_root rhgb quiet nopat vga=0x37b 2&lt;br /&gt;        initrd /initrd-2.6.30.5-43.fc11.x86_64.img  /initrd-plymouth.img&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a shell script which will generate the two images. It is based on existing scripts in the Plymouth codebase.  &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;#&lt;br /&gt;#&lt;br /&gt;#  FPMurphy  9/12/2009&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;[ -z "$TMPDIR" ] &amp;&amp; TMPDIR="/var/tmp"&lt;br /&gt;&lt;br /&gt;[ -z "$LIBEXECDIR" ] &amp;&amp; LIBEXECDIR="/usr/libexec"&lt;br /&gt;[ -z "$DATADIR" ] &amp;&amp; DATADIR="/usr/share"&lt;br /&gt;[ -z "$PLYMOUTH_PLUGIN_PATH" ] &amp;&amp; PLYMOUTH_PLUGIN_PATH="$(plymouth --get-splash-plugin-path)"&lt;br /&gt;[ -z "$PLYMOUTH_LOGO_FILE" ] &amp;&amp; PLYMOUTH_LOGO_FILE="/usr/share/plymouth/bizcom.png"&lt;br /&gt;[ -z "$PLYMOUTH_THEME_NAME" ] &amp;&amp; PLYMOUTH_THEME_NAME=$(plymouth-set-default-theme)&lt;br /&gt;&lt;br /&gt;[ -z "$PLYMOUTH_IMAGE_FILE" ] &amp;&amp; PLYMOUTH_IMAGE_FILE="/boot/initrd-plymouth.img"&lt;br /&gt;[ -z "$IMAGE_FILE" ] &amp;&amp; IMAGE_FILE="/boot/initrd-$(uname -r).img"&lt;br /&gt;&lt;br /&gt;if [ -z "$PLYMOUTH_POPULATE_SOURCE_FUNCTIONS" ]; then&lt;br /&gt;    if [ -f "${LIBEXECDIR}/initrd-functions" ]; then&lt;br /&gt;        PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="${LIBEXECDIR}/initrd-functions"&lt;br /&gt;    fi&lt;br /&gt;    if [ -f "${DATADIR}/dracut/dracut-functions" ]; then&lt;br /&gt;        PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="${DATADIR}/dracut/dracut-functions"&lt;br /&gt;    fi&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ -n "$PLYMOUTH_POPULATE_SOURCE_FUNCTIONS" ]; then&lt;br /&gt;    source $PLYMOUTH_POPULATE_SOURCE_FUNCTIONS&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ " $(type -t inst) " != " function " ]; then&lt;br /&gt;    echo "Need 'inst' function, try setting PLYMOUTH_POPULATE_SOURCE_FUNCTIONS to a file that defines it" 1&gt;&amp;2&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ " $(type -t set_verbose) " != " function " ]; then&lt;br /&gt;    function set_verbose { true; }&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;Function usage() {&lt;br /&gt;    local output="/dev/stdout"&lt;br /&gt;    local rc=0&lt;br /&gt;    if [ "$1" == "error" ]; then&lt;br /&gt;        output="/dev/stderr"&lt;br /&gt;        rc=1&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    echo "usage: plymouth_setup_initrds [ --verbose | -v ]" &gt; $output&lt;br /&gt;    exit $rc&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;verbose=false&lt;br /&gt;INITRDDIR=""&lt;br /&gt;while [ $# -gt 0 ]; do&lt;br /&gt;    case $1 in&lt;br /&gt;        --verbose|-v)&lt;br /&gt;            verbose=true&lt;br /&gt;            ;;&lt;br /&gt;        --help|-h)&lt;br /&gt;            usage normal&lt;br /&gt;            ;;&lt;br /&gt;        *)&lt;br /&gt;            usage error&lt;br /&gt;            break&lt;br /&gt;            ;;&lt;br /&gt;    esac&lt;br /&gt;    shift&lt;br /&gt;done&lt;br /&gt;set_verbose $verbose || :&lt;br /&gt;&lt;br /&gt;CURRENTDIR=`pwd`&lt;br /&gt;INITRDDIR=`mktemp -d ${TMPDIR}/initrd.XXXXXX`&lt;br /&gt;[ -z "$INITRDDIR" ] &amp;&amp; {&lt;br /&gt;     echo "mktemp failed"&lt;br /&gt;     exit 1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;mkdir -p ${INITRDDIR}${DATADIR}/plymouth/themes&lt;br /&gt;inst /sbin/plymouthd $INITRDDIR /bin/plymouthd&lt;br /&gt;inst /bin/plymouth $INITRDDIR&lt;br /&gt;inst ${DATADIR}/plymouth/themes/text/text.plymouth $INITRDDIR&lt;br /&gt;inst ${PLYMOUTH_PLUGIN_PATH}/text.so $INITRDDIR&lt;br /&gt;inst ${DATADIR}/plymouth/themes/details/details.plymouth $INITRDDIR&lt;br /&gt;inst ${PLYMOUTH_PLUGIN_PATH}/details.so $INITRDDIR&lt;br /&gt;inst ${PLYMOUTH_LOGO_FILE} $INITRDDIR&lt;br /&gt;inst /etc/system-release $INITRDDIR&lt;br /&gt;if [ -z "$PLYMOUTH_THEME_NAME" ]; then&lt;br /&gt;    echo "No default plymouth plugin is set" &gt; /dev/stderr&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;PLYMOUTH_MODULE_NAME=$(grep "ModuleName *= *" ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ModuleName *= *//')&lt;br /&gt;&lt;br /&gt;if [ ! -f ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so ]; then&lt;br /&gt;    echo "The default plymouth plugin (${PLYMOUTH_MODULE_NAME}) doesn't exist" &gt; /dev/stderr&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;inst ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so $INITRDDIR&lt;br /&gt;&lt;br /&gt;if [ -d ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME} ]; then&lt;br /&gt;    for x in ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/* ; do&lt;br /&gt;        [ ! -f "$x" ] &amp;&amp; break&lt;br /&gt;        inst $x $INITRDDIR&lt;br /&gt;    done&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ -L ${DATADIR}/plymouth/themes/default.plymouth ]; then&lt;br /&gt;    cp -a ${DATADIR}/plymouth/themes/default.plymouth $INITRDDIR${DATADIR}/plymouth/themes&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;# generate the initrd-plymouth image&lt;br /&gt;if [ -f ${PLYMOUTH_IMAGE_FILE} ]; then&lt;br /&gt;     mv ${PLYMOUTH_IMAGE_FILE} ${PLYMOUTH_IMAGE_FILE}.bak&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;echo "Generating image: $PLYMOUTH_IMAGE_FILE"&lt;br /&gt;cd ${INITRDDIR}&lt;br /&gt;rm -f lib*/{ld*,libc*,libdl*,libm*,libz*,libpthread*,libpng*,librt*}&lt;br /&gt;rm -f usr/lib*/libpng*&lt;br /&gt;find . | cpio -H newc --quiet -o | gzip -9 &gt; ${PLYMOUTH_IMAGE_FILE}&lt;br /&gt;&lt;br /&gt;cd ${CURRENTDIR}&lt;br /&gt;rm -rf ${INITRDDIR}&lt;br /&gt;&lt;br /&gt;#  now remove all plymouth items from regular initrd&lt;br /&gt;INITRDDIR=`mktemp -d ${TMPDIR}/initrd.XXXXXX`&lt;br /&gt;[ -z "$INITRDDIR" ] &amp;&amp; {&lt;br /&gt;     echo "mktemp failed"&lt;br /&gt;     exit 1&lt;br /&gt;}&lt;br /&gt;cd ${INITRDDIR}&lt;br /&gt;zcat ${IMAGE_FILE} | cpio -i&lt;br /&gt;&lt;br /&gt;rm -f ${INITRDDIR}/bin/plymout*&lt;br /&gt;rm -f ${INITRDDIR}/lib64/libply*&lt;br /&gt;rm -f ${INITRDDIR}/usr/lib64/libply*&lt;br /&gt;rm -rf ${INITRDDIR}/usr/lib64/plymouth&lt;br /&gt;rm -rf ${INITRDDIR}/usr/share/plymouth&lt;br /&gt;&lt;br /&gt;echo "Generating image: ${IMAGE_FILE}"&lt;br /&gt;mv ${IMAGE_FILE} ${IMAGE_FILE}.bak&lt;br /&gt;findall . | cpio -H newc --quiet -o  | gzip -9 &gt; ${IMAGE_FILE}&lt;br /&gt;&lt;br /&gt;cd ${CURRENTDIR}&lt;br /&gt;rm -rf ${INITRDDIR}&lt;br /&gt;&lt;br /&gt;exit 0&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a listing of the generated &lt;em&gt;/boot/initrd-plymouth.img&lt;/em&gt; image.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ lsinitrd /boot/initrd-plymouth.img&lt;br /&gt;drwx------   6 root     root            0 Sep 12 16:43 .&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 etc&lt;br /&gt;-rw-r--r--   1 root     root           29 May 11 18:45 etc/fedora-release&lt;br /&gt;lrwxrwxrwx   1 root     root           14 Sep 12 16:43 etc/system-release -&gt; fedora-release&lt;br /&gt;drwxr-xr-x   4 root     root            0 Sep 12 16:43 usr&lt;br /&gt;drwxr-xr-x   3 root     root            0 Sep 12 16:43 usr/lib64&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 usr/lib64/plymouth&lt;br /&gt;-rwxr-xr-x   1 root     root        27242 Sep 12 01:42 usr/lib64/plymouth/details.so&lt;br /&gt;-rwxr-xr-x   1 root     root        28471 Sep 12 01:42 usr/lib64/plymouth/text.so&lt;br /&gt;-rwxr-xr-x   1 root     root        80032 Sep 12 01:42 usr/lib64/plymouth/space-flares.so&lt;br /&gt;-rwxr-xr-x   1 root     root       200218 Sep 12 01:42 usr/lib64/libplybootsplash.so.2.0.0&lt;br /&gt;lrwxrwxrwx   1 root     root           25 Sep 12 16:43 usr/lib64/libplybootsplash.so.2 -&gt; libplybootsplash.so.2.0.0&lt;br /&gt;drwxr-xr-x   3 root     root            0 Sep 12 16:43 usr/share&lt;br /&gt;drwxr-xr-x   3 root     root            0 Sep 12 16:43 usr/share/plymouth&lt;br /&gt;-rw-r--r--   1 root     root         5529 Sep 12 01:42 usr/share/plymouth/bizcom.png&lt;br /&gt;drwxr-xr-x   5 root     root            0 Sep 12 16:43 usr/share/plymouth/themes&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 usr/share/plymouth/themes/details&lt;br /&gt;-rw-r--r--   1 root     root           84 Sep 12 01:42 usr/share/plymouth/themes/details/details.plymouth&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 usr/share/plymouth/themes/text&lt;br /&gt;-rw-r--r--   1 root     root           98 Sep 12 01:42 usr/share/plymouth/themes/text/text.plymouth&lt;br /&gt;lrwxrwxrwx   1 root     root           20 Sep 12 16:43 usr/share/plymouth/themes/default.plymouth -&gt; solar/solar.plymouth&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 usr/share/plymouth/themes/solar&lt;br /&gt;-rw-r--r--   1 root     root          246 Sep 12 01:42 usr/share/plymouth/themes/solar/progress_bar.png&lt;br /&gt;-rw-r--r--   1 root     root       355666 Sep 12 01:42 usr/share/plymouth/themes/solar/star.png&lt;br /&gt;-rw-r--r--   1 root     root         1896 Sep 12 01:42 usr/share/plymouth/themes/solar/lock.png&lt;br /&gt;-rw-r--r--   1 root     root          165 Sep 12 01:42 usr/share/plymouth/themes/solar/solar.plymouth&lt;br /&gt;-rw-r--r--   1 root     root          296 Sep 12 01:42 usr/share/plymouth/themes/solar/bullet.png&lt;br /&gt;-rw-r--r--   1 root     root          870 Sep 12 01:42 usr/share/plymouth/themes/solar/box.png&lt;br /&gt;-rw-r--r--   1 root     root          350 Sep 12 01:42 usr/share/plymouth/themes/solar/entry.png&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 lib64&lt;br /&gt;-rwxr-xr-x   1 root     root       293522 Sep 12 01:42 lib64/libply.so.2.0.0&lt;br /&gt;lrwxrwxrwx   1 root     root           15 Sep 12 16:43 lib64/libply.so.2 -&gt; libply.so.2.0.0&lt;br /&gt;drwxr-xr-x   2 root     root            0 Sep 12 16:43 bin&lt;br /&gt;-rwxr-xr-x   1 root     root        70256 Sep 12 01:42 bin/plymouth&lt;br /&gt;-rwxr-xr-x   1 root     root       110319 Sep 12 01:42 bin/plymouthd&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;As you can see it only contains Plymouth-related files. It does not contain the &lt;em&gt;label&lt;/em&gt; plugin because this is loaded in using &lt;em&gt;dlopen()&lt;/em&gt; when needed.&lt;br /&gt;&lt;br /&gt;You can debug Plymouth by adding &lt;em&gt;plymouth:debug&lt;/em&gt;, &lt;em&gt;plymouth:debug=file:&lt;/em&gt;, or &lt;em&gt;plymouth:debug=file:path_to_log_file&lt;/em&gt; on the kernel command line.  The default file is &lt;em&gt;/var/log/plymouth-debug.log&lt;/em&gt; if logging to a file is specified but no file is specified, i.e. option two. Other kernel command line options include &lt;em&gt;console=/dev/what_ever_works&lt;/em&gt; to override the default console (&lt;em&gt;/dev/tty0&lt;/em&gt;) and &lt;em&gt;plymouth:splash=name_of_theme&lt;/em&gt; to override the default theme.  &lt;br /&gt;&lt;br /&gt;There are also a number of key combinations such as CTRL-L to redraw the screen, CTRL-V to toggle debug mode and CTRL-T to enable text mode.  Unfortunately I was unable to get any of these key combinations to work.  However the ESC key worked as expected and toggled the display between detailed and the default theme.&lt;br /&gt;&lt;br /&gt;Plymouth does all pixel manipulation in software. There is no &lt;a href='http://en.wikipedia.org/wiki/Graphics_processing_unit'&gt;GPU&lt;/a&gt; acceleration.  It does not use &lt;a href='http://en.wikipedia.org/wiki/MMX_(instruction_set)'&gt;MMX&lt;/a&gt; (Matrix Math Extension) or &lt;a href='http://en.wikipedia.org/wiki/Streaming_SIMD_Extensions'&gt;SSE&lt;/a&gt; (Streaming SIMD Extension)  hence there is no CPU acceleration either.  A plugin that loads a lot of images or does a lot of full screen updates will be slower than one that loads a few images and just updates small parts of the screen.  Much of what has been written about Plymouth in the computing press implies that the goal of Plymouth is to provide a faster boot up experience but that is not an explicit design goal of Plymouth.&lt;br /&gt;&lt;br /&gt;Well that is about all the useful information on Plymouth that I have time to write about at present. After reading this post, I hope you have a better understanding of Plymouth and how it relates to the boot sequence.  Remember however that this project is in active development. and nothing is cast in stone.  For example, the inclusion of &lt;a href='http://fedoraproject.org/wiki/Features/Dracut'&gt;Dracut&lt;/a&gt;, a replacement for &lt;em&gt;nash&lt;/em&gt;, in Fedora 12 (&lt;em&gt;Constantine&lt;/em&gt;) may affect how Plymouth is invoked.  Themes and plug-ins are also rapidly evolving.  &lt;br /&gt;&lt;br /&gt;As Plymouth is implemented in other GNU/Linux distributions such as &lt;a href='http://www.ubuntu.com/'&gt;Ubuntu&lt;/a&gt;, expect to see a flourishing of graphical boot themes from independent authors.  I look forward to that day.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-6743235636847197844?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/6743235636847197844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/09/project-plymouth.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/6743235636847197844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/6743235636847197844'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/09/project-plymouth.html' title='Project Plymouth'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_IrJjVkDo0pg/Sq5cSfkfbSI/AAAAAAAAAHM/BirpkOREFnc/s72-c/VGA1.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-2007963579180637334</id><published>2009-09-07T23:40:00.001-04:00</published><updated>2009-09-08T22:50:58.820-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Fedora'/><category scheme='http://www.blogger.com/atom/ns#' term='HAL'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomboy'/><category scheme='http://www.blogger.com/atom/ns#' term='D-Bus'/><title type='text'>Ruby D-Bus and Fedora 11</title><content type='html'>Earlier this year I wrote a number of posts about monitoring and interacting with D-Bus using shell scripts.  In this post I use Ruby to monitor and interact with D-Bus enabled applications.  If you are unfamiliar with D-Bus, a good starting point is this Freedesktop.org &lt;a href="http://www.freedesktop.org/wiki/IntroductionToDBus"&gt;tutorial&lt;/a&gt; by the authors of the D-Bus specification.&lt;br /&gt;&lt;br /&gt;I used the standard out-of-the-box version of &lt;a href='http://www.ruby-lang.org'&gt;Ruby&lt;/a&gt; which comes with Fedora 11, i.e. &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ ruby --version&lt;br /&gt;ruby 1.8.6 (2009-06-08 patchlevel 369) [x86_64-linux] &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Those readers who are familiar with Ruby will recognize that this version of Ruby is quite old by Ruby standards and is in maintenance mode with Kirk Haines of &lt;a href='http://www.engineyard.com'&gt;Engine Yard&lt;/a&gt; being the lead maintainer.  Hopefully a 1.9 version of Ruby will be included in the official repositories for Fedora 12.  &lt;br /&gt;&lt;br /&gt;I also installed the latest version (0.2.9 "I'm not dead") of &lt;a href='https://trac.luon.net/ruby-dbus/'&gt;ruby-dbus&lt;/a&gt; which comes as a compressed tarball rather than as a gem.  This project was recently taken over by Martin Vidner, who works for Novell in their Prague development group, after a long period of no activity by the original developers. An introduction to and a tutorial on &lt;em&gt;ruby-dbus&lt;/em&gt;  is available &lt;a href='http://trac.luon.net/data/ruby-dbus/tutorial/'&gt;here&lt;/a&gt;. It needs to be updated and expanded to include all the interfaces and methods but it is a good introduction to the general concepts.&lt;br /&gt;&lt;br /&gt;Introspection is core to D-Bus scripting.  Here is one way to introspect the D-Bus system bus and output the resulting introspection data in XML format.  The introspection data format is specified by the &lt;a href='http://dbus.freedesktop.org/doc/dbus-specification.html'&gt;D-Bus Specification&lt;/a&gt;.   The &lt;em&gt;introspect_data&lt;/em&gt; method does all the heavy lifting.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SystemBus.instance&lt;br /&gt;xml = bus.introspect_data("org.freedesktop.DBus", "/org/freedesktop/DBus/Introspectable")&lt;br /&gt;puts xml&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output from my computer which is running Fedora 11:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;&amp;lt;!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"&lt;br /&gt;"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"&amp;gt;&lt;br /&gt;&amp;lt;node&amp;gt;&lt;br /&gt;  &amp;lt;interface name="org.freedesktop.DBus.Introspectable"&amp;gt;&lt;br /&gt;    &amp;lt;method name="Introspect"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="data" direction="out" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;  &amp;lt;/interface&amp;gt;&lt;br /&gt;  &amp;lt;interface name="org.freedesktop.DBus"&amp;gt;&lt;br /&gt;    &amp;lt;method name="Hello"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="RequestName"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="u"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="u"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="ReleaseName"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="u"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="StartServiceByName"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="u"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="u"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="UpdateActivationEnvironment"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="a{ss}"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="NameHasOwner"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="b"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="ListNames"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="as"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="ListActivatableNames"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="as"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="AddMatch"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="RemoveMatch"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetNameOwner"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="ListQueuedOwners"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="as"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetConnectionUnixUser"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="u"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetConnectionUnixProcessID"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="u"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetAdtAuditSessionData"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="ay"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetConnectionSELinuxSecurityContext"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="ay"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="ReloadConfig"&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetId"&amp;gt;&lt;br /&gt;      &amp;lt;arg direction="out" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;signal name="NameOwnerChanged"&amp;gt;&lt;br /&gt;      &amp;lt;arg type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/signal&amp;gt;&lt;br /&gt;    &amp;lt;signal name="NameLost"&amp;gt;&lt;br /&gt;      &amp;lt;arg type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/signal&amp;gt;&lt;br /&gt;    &amp;lt;signal name="NameAcquired"&amp;gt;&lt;br /&gt;      &amp;lt;arg type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/signal&amp;gt;&lt;br /&gt;  &amp;lt;/interface&amp;gt;&lt;br /&gt;&amp;lt;/node&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The following example uses the &lt;em&gt;introspect&lt;/em&gt; method instead of the &lt;em&gt;introspect_data&lt;/em&gt; method to  enumerate a list of the available services using the &lt;em&gt;ListActivatableNames&lt;/em&gt; method.  I am going to assume that you are familiar with the Ruby language.so concepts such as looping and arrays do not need explanation.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;require 'dbus'  &lt;br /&gt;  &lt;br /&gt;bus = DBus::SystemBus.instance  &lt;br /&gt;proxy = bus.introspect("org.freedesktop.DBus", "/org/freedesktop/DBus/ListActivatableNames")  &lt;br /&gt;&lt;br /&gt;bus.proxy.ListActivatableNames[0].each do |service|  &lt;br /&gt;   puts "#{service}"  &lt;br /&gt;end  &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;This is the output: &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;org.freedesktop.DBus&lt;br /&gt;org.freedesktop.DeviceKit.Disks&lt;br /&gt;org.fedoraproject.Setroubleshootd&lt;br /&gt;com.hp.hplip&lt;br /&gt;org.fedoraproject.Config.Services&lt;br /&gt;org.freedesktop.ConsoleKit&lt;br /&gt;org.gnome.CPUFreqSelector&lt;br /&gt;net.reactivated.Fprint&lt;br /&gt;org.freedesktop.PackageKit&lt;br /&gt;org.freedesktop.DeviceKit&lt;br /&gt;org.freedesktop.NetworkManagerSystemSettings&lt;br /&gt;org.gnome.ClockApplet.Mechanism&lt;br /&gt;org.kerneloops.submit&lt;br /&gt;org.freedesktop.PolicyKit&lt;br /&gt;org.freedesktop.Gypsy&lt;br /&gt;org.gnome.GConf.Defaults&lt;br /&gt;fi.epitest.hostap.WPASupplicant&lt;br /&gt;org.gnome.SystemMonitor.Mechanism&lt;br /&gt;org.freedesktop.DeviceKit.Power&lt;br /&gt;org.freedesktop.nm_dispatcher&lt;br /&gt;org.opensuse.CupsPkHelper.Mechanism&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;You can query devices via the D-Bus interface to &lt;a href='http://www.freedesktop.org/wiki/Software/hal'&gt;HAL&lt;/a&gt; as the following examples demonstrate.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'  &lt;br /&gt;  &lt;br /&gt;bus = DBus::SystemBus.instance  &lt;br /&gt;xml = bus.introspect_data("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer")  &lt;br /&gt;puts xml&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is what is outputted when this script is executed:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;&amp;lt;!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"&lt;br /&gt;"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"&amp;gt;&lt;br /&gt;&amp;lt;node&amp;gt;&lt;br /&gt;  &amp;lt;interface name="org.freedesktop.Hal.Device"&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetAllProperties"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="properties" direction="out" type="a{sv}"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="SetMultipleProperties"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="properties" direction="in" type="a{sv}"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetProperty"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="key" direction="in" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg name="value" direction="out" type="v"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    ......&lt;br /&gt;    &amp;lt;signal name="InterfaceLockAcquired"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="interface_name" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg name="lock_holder" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg name="num_locks" type="i"/&amp;gt;&lt;br /&gt;    &amp;lt;/signal&amp;gt;&lt;br /&gt;    &amp;lt;signal name="InterfaceLockReleased"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="interface_name" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg name="lock_holder" type="s"/&amp;gt;&lt;br /&gt;      &amp;lt;arg name="num_locks" type="i"/&amp;gt;&lt;br /&gt;    &amp;lt;/signal&amp;gt;&lt;br /&gt;  &amp;lt;/interface&amp;gt;&lt;br /&gt;  .......&lt;br /&gt;  &amp;lt;interface name="org.freedesktop.Hal.Device.CPUFreq"&amp;gt;&lt;br /&gt;    &amp;lt;method name="SetCPUFreqGovernor"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="governor_string" direction="in" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="SetCPUFreqPerformance"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="value" direction="in" type="i"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="SetCPUFreqConsiderNice"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="value" direction="in" type="b"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetCPUFreqGovernor"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="return_code" direction="out" type="s"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetCPUFreqPerformance"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="return_code" direction="out" type="i"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetCPUFreqConsiderNice"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="return_code" direction="out" type="b"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;    &amp;lt;method name="GetCPUFreqAvailableGovernors"&amp;gt;&lt;br /&gt;      &amp;lt;arg name="return_code" direction="out" type="as"/&amp;gt;&lt;br /&gt;    &amp;lt;/method&amp;gt;&lt;br /&gt;  &amp;lt;/interface&amp;gt;&lt;br /&gt;&amp;lt;/node&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is an example of how to output the previous data in a more readable form using the &lt;em&gt;interfaces&lt;/em&gt; method..&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SystemBus.instance&lt;br /&gt;proxy = bus.introspect("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer")&lt;br /&gt;&lt;br /&gt;proxy.interfaces.each do |interface|&lt;br /&gt;   puts "Interface:  #{interface}"&lt;br /&gt;   proxy[interface].methods.each do |key,value|&lt;br /&gt;      puts "     Method: #{key}"&lt;br /&gt;   end&lt;br /&gt;   proxy[interface].signals.each do |key,value|&lt;br /&gt;      puts "     Signal: #{key}"&lt;br /&gt;   end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is an portion of the output: from executing this script.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;Interface:  org.freedesktop.Hal.Device.CPUFreq&lt;br /&gt;     Method: GetCPUFreqConsiderNice&lt;br /&gt;     Method: GetCPUFreqGovernor&lt;br /&gt;     Method: SetCPUFreqPerformance&lt;br /&gt;     Method: GetCPUFreqAvailableGovernors&lt;br /&gt;     Method: SetCPUFreqGovernor&lt;br /&gt;     Method: GetCPUFreqPerformance&lt;br /&gt;     Method: SetCPUFreqConsiderNice&lt;br /&gt;Interface:  org.freedesktop.Hal.Device.SystemPowerManagement&lt;br /&gt;     Method: Shutdown&lt;br /&gt;     Method: SuspendHybrid&lt;br /&gt;     Method: SetPowerSave&lt;br /&gt;     Method: Hibernate&lt;br /&gt;     Method: Reboot&lt;br /&gt;     Method: Suspend&lt;br /&gt;Interface:  org.freedesktop.Hal.Device&lt;br /&gt;     Method: ReleaseInterfaceLock&lt;br /&gt;     Method: ClaimInterface&lt;br /&gt;     Method: Reprobe&lt;br /&gt;     ........&lt;br /&gt;     Method: SetPropertyBoolean&lt;br /&gt;     Signal: InterfaceLockAcquired&lt;br /&gt;     Signal: InterfaceLockReleased&lt;br /&gt;     Signal: PropertyModified&lt;br /&gt;     Signal: Condition&lt;br /&gt;Interface:  org.freedesktop.DBus.Introspectable&lt;br /&gt;     Method: Introspect&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;You can easily drill down to individual interfaces and methods. For example, here is one way to list the set of available CPU frequency governors.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;#&lt;br /&gt;#  &amp;lt;interface name="org.freedesktop.Hal.Device.CPUFreq"&amp;gt;&lt;br /&gt;#    &amp;lt;method name="SetCPUFreqGovernor"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="governor_string" direction="in" type="s"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#    &amp;lt;method name="SetCPUFreqPerformance"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="value" direction="in" type="i"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#    &amp;lt;method name="SetCPUFreqConsiderNice"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="value" direction="in" type="b"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#    &amp;lt;method name="GetCPUFreqGovernor"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="return_code" direction="out" type="s"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#    &amp;lt;method name="GetCPUFreqPerformance"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="return_code" direction="out" type="i"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#    &amp;lt;method name="GetCPUFreqConsiderNice"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="return_code" direction="out" type="b"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#    &amp;lt;method name="GetCPUFreqAvailableGovernors"&amp;gt;&lt;br /&gt;#      &amp;lt;arg name="return_code" direction="out" type="as"/&amp;gt;&lt;br /&gt;#    &amp;lt;/method&amp;gt;&lt;br /&gt;#  &amp;lt;/interface&amp;gt;&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SystemBus.instance&lt;br /&gt;proxy = bus.introspect("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer")&lt;br /&gt;&lt;br /&gt;interface = proxy["org.freedesktop.Hal.Device.CPUFreq"]&lt;br /&gt;governors = interface.GetCPUFreqAvailableGovernors&lt;br /&gt;puts "Available CPU Freq Governors:"&lt;br /&gt;governors[0].each do |gov|&lt;br /&gt;   puts "  #{gov}"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;which produces the following output:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;Available CPU Freq Governors:&lt;br /&gt;  ondemand&lt;br /&gt;  userspace&lt;br /&gt;  performance&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Lots of useful information can be be obtained from the HAL manager interface.  The following script lists all the methods supported by the HAL manager interface and then uses the &lt;em&gt;GetAllDevices&lt;/em&gt; method to enumerate the devices on my computer.   &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SystemBus.instance&lt;br /&gt;proxy = bus.introspect("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")&lt;br /&gt;&lt;br /&gt;puts "HAL manager reports following methods:"&lt;br /&gt;proxy.interfaces[0].each do |interface|&lt;br /&gt;  proxy[interface].methods.each do |key, value|&lt;br /&gt;    puts "   #{key}"&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;interface = proxy["org.freedesktop.Hal.Manager"]&lt;br /&gt;devices = interface.GetAllDevices&lt;br /&gt;puts "\nHAL manager reports following devices:"&lt;br /&gt;devices[0].each do |device|&lt;br /&gt;   puts "  #{device}"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a portion of the output when this script is executed&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;HAL manager reports following methods:&lt;br /&gt;   AcquireGlobalInterfaceLock&lt;br /&gt;   DeviceExists&lt;br /&gt;   CommitToGdl&lt;br /&gt;   GetAllDevicesWithProperties&lt;br /&gt;   FindDeviceByCapability&lt;br /&gt;   NewDevice&lt;br /&gt;   SingletonAddonIsReady&lt;br /&gt;   FindDeviceStringMatch&lt;br /&gt;   GetAllDevices&lt;br /&gt;   ReleaseGlobalInterfaceLock&lt;br /&gt;   Remove&lt;br /&gt;&lt;br /&gt;HAL manager reports following devices:&lt;br /&gt;  /org/freedesktop/Hal/devices/net_ba_cf_03_4e_14_ca&lt;br /&gt;  /org/freedesktop/Hal/devices/volume_part7_size_115326976&lt;br /&gt;  /org/freedesktop/Hal/devices/computer&lt;br /&gt;  /org/freedesktop/Hal/devices/storage_model_DVD_Writer_1070d&lt;br /&gt;  ...............&lt;br /&gt;  /org/freedesktop/Hal/devices/acpi_CPU0&lt;br /&gt;  /org/freedesktop/Hal/devices/acpi_CPU1&lt;br /&gt;  /org/freedesktop/Hal/devices/acpi_CPU2&lt;br /&gt;  /org/freedesktop/Hal/devices/acpi_CPU3&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_2940&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_293e&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_2_0000_00_1a_7_if0&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_2_0000_00_1a_7&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_293c&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1a_2_if0&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1a_2&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_2939&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1a_1_if0&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1a_1&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_2938&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1a_0_if0&lt;br /&gt;  /org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1a_0&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_2937&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_294c&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_10de_640&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_29e1&lt;br /&gt;  /org/freedesktop/Hal/devices/pci_8086_29e0&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The next example uses the D-Bus interface to &lt;a href='http://projects.gnome.org/tomboy/'&gt;Tomboy&lt;/a&gt;,  a desktop note-taking application, to create a simple note, display it for 5 seconds and then delete the note.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SessionBus.instance&lt;br /&gt;service = bus.service("org.gnome.Tomboy")&lt;br /&gt;&lt;br /&gt;tomboy = service.object("/org/gnome/Tomboy/RemoteControl")&lt;br /&gt;tomboy.introspect&lt;br /&gt;tomboy.default_iface = "org.gnome.Tomboy.RemoteControl"&lt;br /&gt;note = tomboy.CreateNamedNote("My Note")[0]&lt;br /&gt;tomboy.SetNoteContents(note, "Hello World")&lt;br /&gt;tomboy.DisplayNote(note)&lt;br /&gt;sleep 5&lt;br /&gt;tomboy.DeleteNote(note)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Note the need to introspect the &lt;em&gt;tomboy&lt;/em&gt; object and set the default interface using the &lt;em&gt;default_iface&lt;/em&gt; method.&lt;br /&gt;&lt;br /&gt;You can also add one or more tags to a Tomboy note and extract comprehensive metadata in XML format as shown in the following example.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SessionBus.instance&lt;br /&gt;service = bus.service("org.gnome.Tomboy")&lt;br /&gt;&lt;br /&gt;tomboy = service.object("/org/gnome/Tomboy/RemoteControl")&lt;br /&gt;tomboy.introspect&lt;br /&gt;tomboy.default_iface = "org.gnome.Tomboy.RemoteControl"&lt;br /&gt;note = tomboy.CreateNamedNote("My Note")[0]&lt;br /&gt;tomboy.SetNoteContents(note, "Hello World")&lt;br /&gt;tomboy.AddTagToNote(note, "blog example")&lt;br /&gt;tomboy.DisplayNote(note)&lt;br /&gt;sleep 5&lt;br /&gt;xml = tomboy.GetNoteCompleteXml(note)&lt;br /&gt;tomboy.DeleteNote(note)&lt;br /&gt;&lt;br /&gt;puts xml&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the XML that is outputted when this script is executed:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt;&lt;br /&gt;&amp;lt;note version="0.3" xmlns:link="http://beatniksoftware.com/tomboy/link" xmlns:size="http://beatniksoftware.com/tomboy/size" xmlns="http://beatniksoftware.com/tomboy"&amp;gt;&lt;br /&gt;  &amp;lt;title&amp;gt;My Note&amp;lt;/title&amp;gt;&lt;br /&gt;  &amp;lt;text xml:space="preserve"&amp;gt;&amp;lt;note-content version="0.1"&amp;gt;Hello World&amp;lt;/note-content&amp;gt;&amp;lt;/text&amp;gt;&lt;br /&gt;  &amp;lt;last-change-date&amp;gt;2009-09-07T15:44:10.2178650-04:00&amp;lt;/last-change-date&amp;gt;&lt;br /&gt;  &amp;lt;last-metadata-change-date&amp;gt;2009-09-07T15:44:10.2212100-04:00&amp;lt;/last-metadata-change-date&amp;gt;&lt;br /&gt;  &amp;lt;create-date&amp;gt;2009-09-07T15:44:10.2142940-04:00&amp;lt;/create-date&amp;gt;&lt;br /&gt;  &amp;lt;cursor-position&amp;gt;37&amp;lt;/cursor-position&amp;gt;&lt;br /&gt;  &amp;lt;width&amp;gt;450&amp;lt;/width&amp;gt;&lt;br /&gt;  &amp;lt;height&amp;gt;360&amp;lt;/height&amp;gt;&lt;br /&gt;  &amp;lt;x&amp;gt;1440&amp;lt;/x&amp;gt;&lt;br /&gt;  &amp;lt;y&amp;gt;0&amp;lt;/y&amp;gt;&lt;br /&gt;  &amp;lt;tags&amp;gt;&lt;br /&gt;    &amp;lt;tag&amp;gt;blog example&amp;lt;/tag&amp;gt;&lt;br /&gt;  &amp;lt;/tags&amp;gt;&lt;br /&gt;  &amp;lt;open-on-startup&amp;gt;False&amp;lt;/open-on-startup&amp;gt;&lt;br /&gt;&amp;lt;/note&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The next example show you how to monitor D-Bus messages and act upon certain messages.  You can do this using D-Bus signals.  Suppose, for example, you want to monitor activity relating to Tomboy notes such as when Tomboy notes are created.  First of all you need to find out what D-Bus signals Tomboy supports. This is easy to do using introspection as shown in the following script.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SessionBus.instance&lt;br /&gt;service = bus.service("org.gnome.Tomboy")&lt;br /&gt;&lt;br /&gt;tomboy = service.object("/org/gnome/Tomboy/RemoteControl")&lt;br /&gt;tomboy.introspect&lt;br /&gt;tomboy.default_iface = "org.gnome.Tomboy.RemoteControl"&lt;br /&gt;puts "List of supported signals:"&lt;br /&gt;tomboy.signals.each do |key,value|&lt;br /&gt;   puts "  #{key}"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;List of supported signals:&lt;br /&gt;  NoteSaved&lt;br /&gt;  NoteAdded&lt;br /&gt;  NoteDeleted&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;As you can see the version of Tomboy on my computer emits three D-Bus signals - &lt;em&gt;NoteAdded&lt;/em&gt; when a note is added, &lt;em&gt;NoteSaved&lt;/em&gt; when a note is saved, and &lt;em&gt;NoteDeleted&lt;/em&gt; when a note is deleted. &lt;br /&gt;&lt;br /&gt;The following script outputs a message each time a Tomboy note is created, saved or deleted.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'dbus'&lt;br /&gt;&lt;br /&gt;bus = DBus::SessionBus.instance&lt;br /&gt;&lt;br /&gt;match = DBus::MatchRule.new&lt;br /&gt;match.type = "signal"&lt;br /&gt;match.interface = "org.gnome.Tomboy.RemoteControl"&lt;br /&gt;match.path = "/org/gnome/Tomboy/RemoteControl"&lt;br /&gt;&lt;br /&gt;bus.add_match(match) do |msg, misc|&lt;br /&gt;    puts "#{msg.member}  #{msg.params[0]}"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;main = DBus::Main.new&lt;br /&gt;main &lt;&lt; bus&lt;br /&gt;main.run&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is what is outputted when a single Tomboy note is created, saved and then deleted.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;NoteAdded  note://tomboy/56587548-7535-4e21-a4b3-3ee85ffa7756&lt;br /&gt;NoteSaved  note://tomboy/56587548-7535-4e21-a4b3-3ee85ffa7756&lt;br /&gt;NoteDeleted  note://tomboy/56587548-7535-4e21-a4b3-3ee85ffa7756&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Well that's all for now.  There is a lot more that you can do using &lt;em&gt;ruby-dbus&lt;/em&gt; but I will leave it up to you to go explore the possibilities.  The best place to discover what is possible is to study the &lt;em&gt;ruby-dbus&lt;/em&gt;source code.  It is fairly compact and terse but logically laid out.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-2007963579180637334?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/2007963579180637334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/09/ruby-d-bus-and-fedora-11.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/2007963579180637334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/2007963579180637334'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/09/ruby-d-bus-and-fedora-11.html' title='Ruby D-Bus and Fedora 11'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-391526497920257550</id><published>2009-08-16T11:40:00.004-04:00</published><updated>2009-08-23T14:07:12.988-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='SNIA'/><category scheme='http://www.blogger.com/atom/ns#' term='RSS'/><category scheme='http://www.blogger.com/atom/ns#' term='XAM'/><title type='text'>RSS Ingester For XAM Reference VIM</title><content type='html'>Recently the &lt;a href='http://www.snia.org/forums/xam/'&gt;SNIA XAM&lt;/a&gt; SDK TWG (Software Development Kit Technical Working Group) released a new version (version 0.7) of the &lt;a href='http://www.snia.org/forums/xam/technology/software/'&gt;XAM SDK&lt;/a&gt; with lots of new features. Included in this SDK was the 5th code drop for the Reference VIM.  Here is a summary of the major new functionality included in this code drop.&lt;br /&gt; &lt;!--skip translation--&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Support for XSet hold and release&lt;/li&gt;&lt;li&gt;Support for XSet autodelete and shred policies&lt;/li&gt;&lt;li&gt;Support for simple where clauses in level 1 queries&lt;/li&gt;&lt;li&gt;Support for retention policies including XSet import and export&lt;/li&gt;&lt;li&gt;Support for asynchronous methods&lt;/li&gt;&lt;li&gt;Support for level 2 queries&lt;/li&gt;&lt;/ul&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Also recently released were &lt;a href='http://www.snia.org/tech_activities/standards/curr_standards/xam/'&gt;version 1.01&lt;/a&gt; of the XAM technical positions (AKA specifications).  If you are familiar with version 1.0 of these three documents you may just want to read the errata for each document which is also available on the website. &lt;br /&gt;&lt;br /&gt;I decided to test the Reference VIM by writing a small Java application to ingest the RSS feed from my blog, display some information about each post and store this information in the Reference VIM database.  This application uses an XML configuration file to store a list of the RSS feeds to be ingested and the popular &lt;a href='http://rome.dev.java.net/'&gt;ROME&lt;/a&gt; Java library to ingest and parse the individual RSS feeds.  Rather then re-invent the world, it also uses a modified version of the Java source file &lt;em&gt; ExampleBase.java&lt;/em&gt; which is supplied as part of the latest XAM SDK to create and authenticate the connection to the XAM library and Reference VIM.  &lt;br /&gt;&lt;br /&gt;Here is &lt;em&gt;RSS2XAM..java&lt;/em&gt; which is meat of the application.  As you can see, &lt;em&gt;RSS2XAM&lt;/eM&gt; extends &lt;em&gt;ExampleBase&lt;/em&gt;. This is a useful paradigm for writing applications which use the Reference VIM.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;br /&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;//&lt;br /&gt;// RSS2XAM - Ingest RSS feed and add to XAM Storage System&lt;br /&gt;//           using SNIA XAM SDK V0.7 reference VIM&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;import java.net.URL;&lt;br /&gt;import java.net.URLConnection;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.Calendar;&lt;br /&gt;import java.io.File;&lt;br /&gt;&lt;br /&gt;import javax.xml.parsers.DocumentBuilder;&lt;br /&gt;import javax.xml.parsers.DocumentBuilderFactory;&lt;br /&gt;import org.w3c.dom.*;&lt;br /&gt;&lt;br /&gt;import com.sun.syndication.feed.synd.SyndFeed;&lt;br /&gt;import com.sun.syndication.feed.synd.SyndEntry;&lt;br /&gt;import com.sun.syndication.feed.synd.SyndImageImpl;&lt;br /&gt;import com.sun.syndication.io.SyndFeedInput;&lt;br /&gt;import com.sun.syndication.io.XmlReader;&lt;br /&gt;import com.sun.syndication.feed.synd.SyndContentImpl;&lt;br /&gt;import com.sun.syndication.feed.synd.SyndCategory;&lt;br /&gt;&lt;br /&gt;import org.snia.xam.XSet;&lt;br /&gt;import org.snia.xam.XSystem;&lt;br /&gt;import org.snia.xam.XUID;&lt;br /&gt;&lt;br /&gt;public class RSS2XAM&lt;br /&gt;   extends ExampleBase&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    private static void iterateRSSFeed(String rssFeedUrl, XSystem xsystem)&lt;br /&gt;         throws Exception {&lt;br /&gt;&lt;br /&gt;       URLConnection feedUrl = new URL(rssFeedUrl).openConnection();&lt;br /&gt;       SyndFeedInput input = new SyndFeedInput();&lt;br /&gt;       SyndFeed feed = input.build(new XmlReader(feedUrl));&lt;br /&gt;&lt;br /&gt;       System.out.println("RSS feed: " + rssFeedUrl + " (" + feed.getFeedType() + ")");&lt;br /&gt;&lt;br /&gt;       // ingest the feed, display info and create the XSets&lt;br /&gt;       List list = feed.getEntries();&lt;br /&gt;       for (int i = 0 ; i &lt; list.size(); i++)&lt;br /&gt;       {&lt;br /&gt;           SyndEntry entry = (SyndEntry)list.get(i);&lt;br /&gt;&lt;br /&gt;           String display = "Entry: " + i;&lt;br /&gt;           display += "\n  Title: " + entry.getTitle();&lt;br /&gt;           display += "\n  Link: " + entry.getLink();&lt;br /&gt;           display += "\n  Author: " + entry.getAuthor();&lt;br /&gt;           display += "\n  Date Published: " + entry.getPublishedDate();&lt;br /&gt;&lt;br /&gt;           // get the list of categories &lt;br /&gt;           List catList = entry.getCategories();&lt;br /&gt;           String categories = "";&lt;br /&gt;           for (int j = 0 ; j &lt; catList.size(); j++)&lt;br /&gt;           {&lt;br /&gt;               if (j &gt; 0 ) categories += ", ";&lt;br /&gt;               SyndCategory cat = (SyndCategory)catList.get(j);&lt;br /&gt;               categories += cat.getName();&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           display += "\n  Categories: " + categories;&lt;br /&gt;           System.out.println(display);&lt;br /&gt;&lt;br /&gt;           XSet xset = xsystem.createXSet(XSet.MODE_UNRESTRICTED);&lt;br /&gt;           xset.createProperty("com.fpmurphy.rss.title", false, entry.getTitle());&lt;br /&gt;           xset.createProperty("com.fpmurphy.rss.link", false, entry.getLink());&lt;br /&gt;           xset.createProperty("com.fpmurphy.rss.author", false, entry.getAuthor());&lt;br /&gt;           xset.createProperty("com.fpmurphy.rss.categories", false, categories);&lt;br /&gt;           Calendar cal=Calendar.getInstance();&lt;br /&gt;           cal.setTime(entry.getPublishedDate());&lt;br /&gt;           xset.createProperty("com.fpmurphy.rss.published_date", false, cal);&lt;br /&gt;&lt;br /&gt;           XUID xuid  = xset.commit();&lt;br /&gt;           System.out.println("  XSet XUID ==&gt; " + xuid.toString() + "\n");&lt;br /&gt;           xset.close();&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public static void main(String argv[]) {&lt;br /&gt;&lt;br /&gt;      try {&lt;br /&gt;          File file = new File("rss.xml");&lt;br /&gt;&lt;br /&gt;          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;          DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;          Document document = db.parse(file);&lt;br /&gt;          document.getDocumentElement().normalize();&lt;br /&gt;&lt;br /&gt;          // init, load Reference VIM, and authenticate &lt;br /&gt;          System.out.println("Connecting to Reference VIM");&lt;br /&gt;          initLibrary();&lt;br /&gt;          XSystem xsystem = connectToVIM(s_xri);&lt;br /&gt;          authenticate(xsystem);&lt;br /&gt;&lt;br /&gt;          // parse the rss.xml&lt;br /&gt;          NodeList nodeList = document.getElementsByTagName("feed");&lt;br /&gt;          int totalFeed = nodeList.getLength();&lt;br /&gt;          System.out.println("Number of Feeds: " + totalFeed);&lt;br /&gt;&lt;br /&gt;          for (int i = 0; i &lt; nodeList.getLength(); i++) {&lt;br /&gt;             Node feedNode = nodeList.item(i);&lt;br /&gt;             if (feedNode instanceof Element) {&lt;br /&gt;                Element child = (Element) feedNode;&lt;br /&gt;                String check = child.getAttribute("check");&lt;br /&gt;                String rssFeedUrl = child.getTextContent();&lt;br /&gt;&lt;br /&gt;                // hand off to do the work&lt;br /&gt;                iterateRSSFeed(rssFeedUrl, xsystem);&lt;br /&gt;             }&lt;br /&gt;          }&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a copy of the modified &lt;em&gt;exampleBase.java&lt;/em&gt;. If you compare it to the original source code in the XAM SDK (&lt;em&gt;...//Java_Reference_VIM/examples/ExampleBase.java&lt;/em&gt;) you will see that most of the changes are minor simplifications.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;br /&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;/*&lt;br /&gt; * Copyright (c) 2009, Sun Microsystems, Inc.&lt;br /&gt; * Copyright (c) 2009, The Storage Networking Industry Association.&lt;br /&gt; *  &lt;br /&gt; * Redistribution and use in source and binary forms, with or without &lt;br /&gt; * modification, are permitted provided that the following conditions are met:&lt;br /&gt; *  &lt;br /&gt; * Redistributions of source code must retain the above copyright notice, &lt;br /&gt; * this list of conditions and the following disclaimer.&lt;br /&gt; *  &lt;br /&gt; * Redistributions in binary form must reproduce the above copyright notice, &lt;br /&gt; * this list of conditions and the following disclaimer in the documentation &lt;br /&gt; * and/or other materials provided with the distribution.&lt;br /&gt; *  &lt;br /&gt; * Neither the name of The Storage Networking Industry Association (SNIA) nor &lt;br /&gt; * the names of its contributors may be used to endorse or promote products &lt;br /&gt; * derived from this software without specific prior written permission.&lt;br /&gt; *  &lt;br /&gt; *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" &lt;br /&gt; *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE &lt;br /&gt; *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE &lt;br /&gt; *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE &lt;br /&gt; *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR &lt;br /&gt; *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF &lt;br /&gt; *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS &lt;br /&gt; *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN &lt;br /&gt; *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) &lt;br /&gt; *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF &lt;br /&gt; *  THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;import java.io.ByteArrayOutputStream;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;import org.snia.xam.XAMException;&lt;br /&gt;import org.snia.xam.XAMLibrary;&lt;br /&gt;import org.snia.xam.XSystem;&lt;br /&gt;import org.snia.xam.base.XAMImplementation;&lt;br /&gt;import org.snia.xam.util.SASLUtils;&lt;br /&gt;import org.snia.xam.vim.reference.ReferenceAuthenticationStatus;&lt;br /&gt;import org.snia.xam.vim.reference.utils.ReferenceSaslUtils;&lt;br /&gt;&lt;br /&gt;public class ExampleBase {&lt;br /&gt;&lt;br /&gt;    public static final String PROP_FILE = "rss2xam.props";&lt;br /&gt;    public static final String XRI_PROP  = "xam.xri";&lt;br /&gt;    public static final String CONFIG_PROP = "xam.vims";&lt;br /&gt;    public static final String USER_PROP = "xam.username";&lt;br /&gt;    public static final String PASS_PROP = "xam.password";&lt;br /&gt;&lt;br /&gt;    protected static final String DEFAULT_USER = "test";&lt;br /&gt;    protected static final String DEFAULT_PASS = "test";&lt;br /&gt;    protected static String     s_pass;&lt;br /&gt;    protected static String     s_user;&lt;br /&gt;    protected static XAMLibrary s_xam;&lt;br /&gt;    protected static String     s_xri;&lt;br /&gt;&lt;br /&gt;    public static void initLibrary() throws Exception {&lt;br /&gt;        System.out.println("\nInitializing VIM");&lt;br /&gt;&lt;br /&gt;        Properties props = new Properties();&lt;br /&gt;        String testPropFile = System.getProperty(PROP_FILE);&lt;br /&gt;        if (testPropFile == null)&lt;br /&gt;            testPropFile = PROP_FILE;&lt;br /&gt;&lt;br /&gt;        System.out.println("Loading properties from file: " + testPropFile);&lt;br /&gt;        props.load(new FileInputStream(testPropFile));&lt;br /&gt;&lt;br /&gt;        s_xri = props.getProperty(XRI_PROP);&lt;br /&gt;&lt;br /&gt;        s_user = props.getProperty(USER_PROP, DEFAULT_USER);&lt;br /&gt;        s_pass = props.getProperty(PASS_PROP, DEFAULT_PASS);&lt;br /&gt;&lt;br /&gt;        System.out.println("VIM Configuration contained in file: " + props.getProperty(CONFIG_PROP));&lt;br /&gt;        s_xam = new XAMImplementation(props.getProperty(CONFIG_PROP));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static XSystem connectToVIM(String xri) throws Exception {&lt;br /&gt;        XSystem xsystem = null;&lt;br /&gt;        System.out.println("Connection arguments: " + xri);&lt;br /&gt;        xsystem = s_xam.connect(xri);&lt;br /&gt;        return xsystem;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void authenticate(XSystem system) throws XAMException {&lt;br /&gt;        String defMech = system.getString(XSystem.XAM_XSYSTEM_AUTH_SASL_DEFAULT);&lt;br /&gt;        ByteArrayOutputStream response = new ByteArrayOutputStream(200);&lt;br /&gt;        byte[] inputData = null;&lt;br /&gt;        int retValue = 0;&lt;br /&gt;        if (defMech.equals(ReferenceSaslUtils.SASL_MECHANISM_ANONYMOUS)) {&lt;br /&gt;            retValue = system.authenticate(inputData, response);&lt;br /&gt;        } else if (defMech.equals(SASLUtils.SASL_PLAIN)) {&lt;br /&gt;            byte[] creds = ReferenceSaslUtils.encodeSASLPlain(null,&lt;br /&gt;                    ReferenceAuthenticationStatus.TEST_USERNAME,&lt;br /&gt;                    ReferenceAuthenticationStatus.TEST_PASSWORD);&lt;br /&gt;            retValue = system.authenticate(creds, response);&lt;br /&gt;        } else {&lt;br /&gt;            throw new XAMException("Unknown SASL mechanism " + defMech);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (retValue != XSystem.XAM_SASL_COMPLETE) {&lt;br /&gt;            throw new XAMException("Failed to authenticate.");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a copy of my &lt;em&gt;rss2xam.props&lt;/em&gt;.  I am storing the generated XSets at &lt;em&gt;/home/fpm/rss/store&lt;/em&gt; but you can specify any directory you like by modifying the &lt;em&gt;dir=&lt;/em&gt; directive on the second line of this file.  Make sure that this directory exists and is writeable or you will get an exception when you invoke the application.  I will leave it to you to modify the source to test that the specified directory exists and is writeable.   As you can see, this file also specifies that the Reference VIM configuration file (&lt;em&gt;vim.config&lt;/em&gt;) exists in the current directory.  Again you are free to change the location to wherever you like.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;xam.vims=./vim.config&lt;br /&gt;xam.xri=snia-xam://SNIA_Reference_VIM!localhost?dir=/home/fpm/rss/store&lt;br /&gt;xam.username=testuser&lt;br /&gt;xam.password=testpasswd&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is my &lt;em&gt;vim.config&lt;/em&gt;:  It is basically the same as comes with the XAM SDK.  The only difference is that I create a new log every time the application is invoked rather than appending to the existing log.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;.xam.config.vim.alias.SNIA_Reference_VIM=org.snia.xam.vim.reference.ReferenceVIM&lt;br /&gt;xam_boolean..xam.log.append=false&lt;br /&gt;xam_int..xam.log.max.size=200&lt;br /&gt;xam_int..xam.log.verbosity=1&lt;br /&gt;xam_int..xam.log.level=5&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a copy of my &lt;em&gt;rss.xml&lt;/em&gt;. It contains a simple feed i.e. this blog. You can add more feeds like you like.  The &lt;em&gt;check&lt;/em&gt; attribute is for future use and is not used by this application.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;&amp;lt;config&amp;gt;&lt;br /&gt;   &amp;lt;feed check="10"&amp;gt;http://blog.fpmurphy.com/feed&amp;lt;/feed&amp;gt;&lt;br /&gt;&amp;lt;/config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output when this application is complied and invoked.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ javac RSS2XAM.java ExampleBase.java&lt;br /&gt;$ java RSS2XAM&lt;br /&gt;Connecting to Reference VIM&lt;br /&gt;Initializing VIM&lt;br /&gt;Loading properties from file: rss.props&lt;br /&gt;VIM Configuration contained in file: ./vim.config&lt;br /&gt;Connection arguments: snia-xam://SNIA_Reference_VIM!localhost?dir=/home/fpm/rss/store&lt;br /&gt;&lt;br /&gt;Number of Feeds: 1&lt;br /&gt;RSS feed: http://blog.fpmurphy.com/feed (rss_2.0)&lt;br /&gt;&lt;br /&gt;Entry: 0&lt;br /&gt;  Title: Amazon SimpleDB Typica Tutorial&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/08/amazon-simpledb-typica-tutorial.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Tue Aug 04 12:35:14 GMT-05:00 2009&lt;br /&gt;  Categories: AWS, Java, XAM&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAqbu8xMjUwNDc2OTYwNzcwAcSLfePaTUlTnoaEkQ5kBOgDBBh2&lt;br /&gt;&lt;br /&gt;Entry: 1&lt;br /&gt;  Title: XAM Query Language&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/07/xam-query-language.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Sun Jul 19 10:10:41 GMT-05:00 2009&lt;br /&gt;  Categories: XAM, XSet, XStream, XSystem, SNIA&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAqbH8xMjUwNDc2OTYwODExAjloAZmNdUUPto94Weh/11seuv3/&lt;br /&gt;&lt;br /&gt;Entry: 2&lt;br /&gt;  Title: Linux HPET Support&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/07/linux-hpet-support.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Mon Jul 06 02:50:03 GMT-05:00 2009&lt;br /&gt;  Categories: C, HPET, Linux&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAquJ0xMjUwNDc2OTYwODMxAxk6BG7OQErMh3iqx3BMNwYGbeYJ&lt;br /&gt;&lt;br /&gt;Entry: 3&lt;br /&gt;  Title: XAM Mandated Fields&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/06/xam-mandated-fields.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Mon Jun 29 21:07:04 GMT-05:00 2009&lt;br /&gt;  Categories: XAM, SNIA&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAqUWoxMjUwNDc2OTYwODUxBM5rT72XVEEeuQvgMU1G47JugiVN&lt;br /&gt;&lt;br /&gt;Entry: 4&lt;br /&gt;  Title: Atahualpa Theme&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/06/blog-now-uses-wordpress-with-atahualpa-theme.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Wed Jun 24 16:14:55 GMT-05:00 2009&lt;br /&gt;  Categories: Uncategorized&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAqGhAxMjUwNDc2OTYwODY5BbZxkkmfZUMmnKAsE/THFApESwu7&lt;br /&gt;&lt;br /&gt;Entry: 5&lt;br /&gt;  Title: XAM Canonical Format&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/06/xam-and-xop.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Sat Jun 20 17:15:00 GMT-05:00 2009&lt;br /&gt;  Categories: XAM, XOP, SNIA&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAq2AkxMjUwNDc2OTYwODg4Bhk1ODii0UOQlaAbfG+dvMwBUxFk&lt;br /&gt;&lt;br /&gt;Entry: 6&lt;br /&gt;  Title: Fedora 11 New Extended File Attributes Namespace&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/06/fedore-11-extended-attibutes-namespace.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Mon Jun 15 09:31:00 GMT-05:00 2009&lt;br /&gt;  Categories: Extended Attributes, Fedora 11, XAM, Linux&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAqa8QxMjUwNDc2OTYwOTA3B3Mj+tqXN0YJjuftnzTjYW5uPlqR&lt;br /&gt;&lt;br /&gt;Entry: 7&lt;br /&gt;  Title: Fedora 11 nVidia Twinview Support&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/06/fedora-11-nvidia-twinview-support.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Thu Jun 11 12:07:00 GMT-05:00 2009&lt;br /&gt;  Categories: Fedora 11, Linux, Twinview, nVidia, Fedora&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAq4JQxMjUwNDc2OTYwOTI5CNTrNQ44okBPnnJFleb57UFNj5t1&lt;br /&gt;&lt;br /&gt;Entry: 8&lt;br /&gt;  Title: Linux Security Capabilities&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/05/linux-security-capabilities.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Thu May 28 10:14:00 GMT-05:00 2009&lt;br /&gt;  Categories: Fedora 11, Linux, POSIX.1e, linux capabilities&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAqURQxMjUwNDc2OTYwOTU1CTY+vTycKkMhgRj22XFJ+CpMdnKG&lt;br /&gt;&lt;br /&gt;Entry: 9&lt;br /&gt;  Title: Windows Parallel Filesystems&lt;br /&gt;  Link: http://blog.fpmurphy.com/2009/05/windows-parallel-filesystems.html&lt;br /&gt;  Author: fpmurphy&lt;br /&gt;  Date Published: Tue May 26 12:27:00 GMT-05:00 2009&lt;br /&gt;  Categories: Windows parallel filesystem, Windows&lt;br /&gt;  XSet XUID ==&gt; AAA6AwAq/jsxMjUwNDc2OTYwOTg0CuIRPc1YkUozqtuI+oCaeTkQx4n7&lt;br /&gt;&lt;br /&gt;$ &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;As you can see from the following listing, the Reference VIM creates an XML file and a subdirectory for each XSet that it creates as well as a Derby database called &lt;em&gt;ReferenceVimDB&lt;/em&gt;.  The name of each XML file and corresponding subdirectory is the XUID of the XSet.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ ls store&lt;br /&gt;ReferenceVimDB                                                     XSet_AAA6AwAqGhAxMjUwNDc2OTYwODY5BbZxkkmfZUMmnKAsE_THFApESwu7&lt;br /&gt;XSet_AAA6AwAq2AkxMjUwNDc2OTYwODg4Bhk1ODii0UOQlaAbfG-dvMwBUxFk      XSet_AAA6AwAqGhAxMjUwNDc2OTYwODY5BbZxkkmfZUMmnKAsE_THFApESwu7.xml&lt;br /&gt;XSet_AAA6AwAq2AkxMjUwNDc2OTYwODg4Bhk1ODii0UOQlaAbfG-dvMwBUxFk.xml  XSet_AAA6AwAq_jsxMjUwNDc2OTYwOTg0CuIRPc1YkUozqtuI-oCaeTkQx4n7&lt;br /&gt;XSet_AAA6AwAq4JQxMjUwNDc2OTYwOTI5CNTrNQ44okBPnnJFleb57UFNj5t1      XSet_AAA6AwAq_jsxMjUwNDc2OTYwOTg0CuIRPc1YkUozqtuI-oCaeTkQx4n7.xml&lt;br /&gt;XSet_AAA6AwAq4JQxMjUwNDc2OTYwOTI5CNTrNQ44okBPnnJFleb57UFNj5t1.xml  XSet_AAA6AwAquJ0xMjUwNDc2OTYwODMxAxk6BG7OQErMh3iqx3BMNwYGbeYJ&lt;br /&gt;XSet_AAA6AwAqa8QxMjUwNDc2OTYwOTA3B3Mj-tqXN0YJjuftnzTjYW5uPlqR      XSet_AAA6AwAquJ0xMjUwNDc2OTYwODMxAxk6BG7OQErMh3iqx3BMNwYGbeYJ.xml&lt;br /&gt;XSet_AAA6AwAqa8QxMjUwNDc2OTYwOTA3B3Mj-tqXN0YJjuftnzTjYW5uPlqR.xml  XSet_AAA6AwAqURQxMjUwNDc2OTYwOTU1CTY-vTycKkMhgRj22XFJ-CpMdnKG&lt;br /&gt;XSet_AAA6AwAqbH8xMjUwNDc2OTYwODExAjloAZmNdUUPto94Weh_11seuv3_      XSet_AAA6AwAqURQxMjUwNDc2OTYwOTU1CTY-vTycKkMhgRj22XFJ-CpMdnKG.xml&lt;br /&gt;XSet_AAA6AwAqbH8xMjUwNDc2OTYwODExAjloAZmNdUUPto94Weh_11seuv3_.xml  XSet_AAA6AwAqUWoxMjUwNDc2OTYwODUxBM5rT72XVEEeuQvgMU1G47JugiVN&lt;br /&gt;XSet_AAA6AwAqbu8xMjUwNDc2OTYwNzcwAcSLfePaTUlTnoaEkQ5kBOgDBBh2      XSet_AAA6AwAqUWoxMjUwNDc2OTYwODUxBM5rT72XVEEeuQvgMU1G47JugiVN.xml&lt;br /&gt;XSet_AAA6AwAqbu8xMjUwNDc2OTYwNzcwAcSLfePaTUlTnoaEkQ5kBOgDBBh2.xml&lt;br /&gt;$ &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the contents of one of these XML files. It corresponds to one post in my blog.  You will see the set of properties the application created for this particular post towards the end of the file.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;xsets xsi:schemaLocation="http://www.snia.org/2007/xam/export/XAMCanonicalXSetDefinition.xsd" xmlns="http://www.snia.org/2007/xam/export" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xop="http://www.w3.org/2004/08/xop/include"&amp;gt;&lt;br /&gt;&amp;lt;version&amp;gt;1.0.0&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;policies&amp;gt;&lt;br /&gt;   &amp;lt;policy name=".xsystem.management.policy.list.org.snia.refvim.default.mgmt.policy" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="35"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;org.snia.refvim.default.mgmt.policy&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/policy&amp;gt;&lt;br /&gt;&amp;lt;/policies&amp;gt;&lt;br /&gt;&amp;lt;xset&amp;gt;&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.hold" type="application/vnd.snia.xam.boolean" binding="false" readOnly="true" length="1"&amp;gt;&lt;br /&gt;      &amp;lt;boolean&amp;gt;false&amp;lt;/boolean&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.management.policy" type="application/vnd.snia.xam.string" binding="true" readOnly="true" length="35"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;org.snia.refvim.default.mgmt.policy&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.retention.base.enabled" type="application/vnd.snia.xam.boolean" binding="true" readOnly="true" length="1"&amp;gt;&lt;br /&gt;      &amp;lt;boolean&amp;gt;true&amp;lt;/boolean&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.retention.base.starttime" type="application/vnd.snia.xam.datetime" binding="true" readOnly="true" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-16T21:42:40.742-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.retention.list.base" type="application/vnd.snia.xam.string" binding="true" readOnly="true" length="4"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;base&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.retention.list.event" type="application/vnd.snia.xam.string" binding="true" readOnly="true" length="5"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;event&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.time.access" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-16T21:42:40.742-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.time.commit" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-16T21:42:40.742-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.time.creation" type="application/vnd.snia.xam.datetime" binding="true" readOnly="true" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-16T21:42:40.724-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.time.residency" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-16T21:42:40.742-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.time.xuid" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-16T21:42:40.742-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name=".xset.xuid" type="application/vnd.snia.xam.xuid" binding="true" readOnly="true" length="42"&amp;gt;&lt;br /&gt;      &amp;lt;xuid&amp;gt;AAA6AwAqbu8xMjUwNDc2OTYwNzcwAcSLfePaTUlTnoaEkQ5kBOgDBBh2&amp;lt;/xuid&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="com.fpmurphy.rss.author" type="application/vnd.snia.xam.string" binding="false" readOnly="false" length="8"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;fpmurphy&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="com.fpmurphy.rss.categories" type="application/vnd.snia.xam.string" binding="false" readOnly="false" length="14"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;AWS, Java, XAM&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="com.fpmurphy.rss.link" type="application/vnd.snia.xam.string" binding="false" readOnly="false" length="69"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;http://blog.fpmurphy.com/2009/08/amazon-simpledb-typica-tutorial.html&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="com.fpmurphy.rss.published_date" type="application/vnd.snia.xam.datetime" binding="false" readOnly="false" length="29"&amp;gt;&lt;br /&gt;      &amp;lt;date&amp;gt;2009-08-04T12:35:14.000-05:00&amp;lt;/date&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="com.fpmurphy.rss.title" type="application/vnd.snia.xam.string" binding="false" readOnly="false" length="31"&amp;gt;&lt;br /&gt;      &amp;lt;string&amp;gt;Amazon SimpleDB Typica Tutorial&amp;lt;/string&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&amp;lt;xstreams&amp;gt;&lt;br /&gt;&amp;lt;/xstreams&amp;gt;&lt;br /&gt;&amp;lt;/xset&amp;gt;&lt;br /&gt;&amp;lt;/xsets&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Well, that is all for now.  As usual, I hope this post was useful to you and that you have increased your knowledge of XAM Storage Systems and how to use the XAM Reference VIM.  &lt;br /&gt;&lt;br /&gt;As the SNIA XAM SDK matures, the Reference VIM is becoming more useful for prototyping a XAM Storage System. Maybe one day, road warriors can use something like the Reference VIM to do useful work while disconnected from their corporate XAM Storage System with the Reference VIM automatically syncing up with the corporate XAM Storage System when a secure network connection becomes available.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-391526497920257550?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/391526497920257550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/08/recently-snia-xam-sdk-twg-software.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/391526497920257550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/391526497920257550'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/08/recently-snia-xam-sdk-twg-software.html' title='RSS Ingester For XAM Reference VIM'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-5050592230189845572</id><published>2009-08-04T23:55:00.000-04:00</published><updated>2009-08-21T23:58:06.656-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SimpleDB'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='XAM'/><category scheme='http://www.blogger.com/atom/ns#' term='AWS'/><title type='text'>Amazon SimpleDB Typica Tutorial</title><content type='html'>While experimenting on how to prototype a Cloud XAM Storage System using &lt;a href='http://aws.amazon.com/'&gt;Amazon Web Services&lt;/a&gt; (AWS), I experimented with the Amazon &lt;a href='http://aws.amazon.com/simpledb/'&gt;SimpleDB&lt;/a&gt; service using Java and the &lt;a href='http://code.google.com/p/typica/'&gt;Typica&lt;/a&gt; AWS client library.  I looked though the Internet for easy examples of how to use this library but found none that I liked - so here is my attempt at a tutorial on using the Typica library with the Amazon SimpleDB service.  &lt;br /&gt;&lt;br /&gt;To use the Typica library, you should download the latest version of the library.  As of the date of this post it is &lt;a href='http://typica.googlecode.com/files/typica-1.6.zip'&gt;typica.1.6&lt;/a&gt;.  Install this library wherever you like; just make sure to add the location to your CLASSPATH.  In Fedora, the standard location is &lt;em&gt;/usr/share/java&lt;/em&gt;. In addition to this library, the following Java libraries (jars)  must also be installed if not already installed and in your CLASSPATH.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;&lt;em&gt;commons-httpclient&lt;/em&gt;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;em&gt;commons-logging&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;        &lt;li&gt;&lt;em&gt;commons-codec&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;        &lt;li&gt;&lt;em&gt;jaxb&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;To run the examples you need an Amazon Web Services SimpleDB account . You will need a credit card for this.  Usage fees apply for using the service but they are relatively low.  At present SimpleDB users pay no usage fees on the first 25 Machine Hours, 1 GB of Data Transfer, and 1 GB of Storage consumed every month. In most use cases, approximately 2 million GET or SELECT API requests can be completed per month before incurring any usage fees. Note that you have to specifically sign up for each of the Amazon Web Service products, i.e. &lt;a href='http:/aws.amazon.com/s3/'&gt;Simple Storage Service&lt;/a&gt; (S3), &lt;a href='http://aws.amazon.com/ec2/'&gt;Elastic Compute Cloud&lt;/a&gt; (EC2), &lt;a href='http://aws.amazon.com/sqs/'&gt;Simple Queue Service&lt;/a&gt; (SQS), SimpleDB, etc.  However, if you have signed up for one AWS product, adding another product is just a couple of key clicks. &lt;br /&gt;&lt;br /&gt;If you cannot sign up for an SimpleDB account, there are a couple of free alternatives which claim to be &lt;em&gt;plug-compatible&lt;/em&gt; with SimpleDB.  I have not yet tried any of these services and the examples in this post will obviously have to be modified somewhat to use these services.  I will discuss this further in the first example below.  M/Gateway Developments &lt;a href='http://gradvs1.mgateway.com/main/index.html?path=mdb'&gt;M/DB&lt;/a&gt; is probably the most well known of such services. &lt;br /&gt;&lt;br /&gt;Before we go any further, here is a quick review of what SimpleDB is and is not.  According to Amazon, SimpleDB is a web service which provides the &lt;em&gt;core database functions of data indexing and querying in the cloud&lt;/em&gt;.  It is not a relational database; it is more of a metadata store.  It is a form of distributed database written in &lt;a href='http://en.wikipedia.org/wiki/Erlang_(programming_language)'&gt;Erlang&lt;/a&gt;.  It requires no schema and automatically indexes your data.  It consists of &lt;em&gt;domains&lt;/em&gt;, &lt;em&gt;items&lt;/em&gt; and &lt;em&gt;attributes&lt;/em&gt;.  A domain is a collection of items.  Items are little hash tables containing attributes i.e. key-value pairs.  As an aside, M/DB supports unlimited attributes per item and unlimited number and size of domains.  &lt;br /&gt;&lt;br /&gt;SimpleDB supports both &lt;a href='http://en.wikipedia.org/wiki/SOAP'&gt;SOAP&lt;/a&gt; and  &lt;a href='http://en.wikipedia.org/wiki/Representational_State_Transfer'&gt;REST&lt;/a&gt; (Representational State Transfer).  The Typica library uses REST.   SimpleDB &lt;a Href='http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/index.html?MakingRESTRequests.html'&gt;REST&lt;/a&gt; calls are made using HTTP GET requests. The Action query parameter provides the method called and the URI specifies the target of the call.  Additional call parameters are specified as HTTP query parameters.  A response message is generated for every request message. The response is an XML document that conforms to a schema.  Check out the &lt;a href='http://docs.amazonwebservices.com/AmazonSimpleDB/latest/GettingStartedGuide'&gt;Getting Started Guide&lt;/a&gt; and the &lt;a href='http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/'&gt;Developer Guide&lt;/a&gt; for further information,&lt;br /&gt;&lt;br /&gt;SimpleDB has some major limitations which you should be aware of.  The principal ones are a maximum of 100 domains per account, 10GB maximum size for a domain, 256 attributes per item and a maximum attribute size of 1024 bytes. Queries also have limitations including a maximum of 2500 items returned per query, a 5 second maximum query runtime, and a maximum query response size of 1Mb for certain types of queries. See the SimpleDB Developers Guide for a full list of the limits. &lt;br /&gt;&lt;br /&gt;&lt;em&gt;Eventual Consistency&lt;/em&gt; is another interesting aspect of SimpleDB. Here is what Amazon have to say about this issue:&lt;br /&gt;&lt;blockquote&gt;Amazon SimpleDB keeps multiple copies of each domain. When data is written or updated [...] and Success is returned, all copies of the data are updated. However, it takes time for the update to propagate to all storage locations. The data will eventually be consistent, but an immediate read might not show the change. Consistency is usually reached within seconds, but a high system load or network partition might increase this time. Repeating a read after a short time should return the updated data. &lt;/blockquote&gt;&lt;br /&gt;Whether this is a real issue in practice, I do not know but it sure sounds like weasel words to me!&lt;br /&gt;&lt;br /&gt;For our &lt;em&gt;Hello World&lt;/em&gt; example, we will just create a SimpleDB domain.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import com.xerox.amazonws.sdb.Domain;&lt;br /&gt;import com.xerox.amazonws.sdb.ListDomainsResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBException;&lt;br /&gt;import com.xerox.amazonws.sdb.SimpleDB;&lt;br /&gt;&lt;br /&gt;public class SDBexample1 {&lt;br /&gt;&lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;      // NOTE - replace AAA with your access key and SSS with your secret key&lt;br /&gt;      SimpleDB simpleDB = new SimpleDB("AAA","SSS");&lt;br /&gt;&lt;br /&gt;      try {&lt;br /&gt;          simpleDB.createDomain("example1");&lt;br /&gt;          System.out.println("created example1 domain");&lt;br /&gt;&lt;br /&gt;          simpleDB.createDomain("example2");&lt;br /&gt;          System.out.println("created example2 domain");&lt;br /&gt;&lt;br /&gt;          ListDomainsResult list = simpleDB.listDomains();&lt;br /&gt;&lt;br /&gt;          Iterator iterator = list.getDomainList().iterator();&lt;br /&gt;          while (iterator.hasNext())&lt;br /&gt;          {&lt;br /&gt;              Domain domain = (Domain) iterator.next();&lt;br /&gt;              System.out.println("List domain: " + domain.getName());&lt;br /&gt;              simpleDB.deleteDomain(domain.getName());&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          System.out.println("deleted all domains");&lt;br /&gt;      } catch (SDBException ex) {&lt;br /&gt;          System.err.println("message : " + ex.getMessage());&lt;br /&gt;          System.err.println("requestID : " + ex.getRequestId());&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;              System.err.println("Error occured: " + e.getMessage());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Documentation for all the classes and methods in the Typica library can be found &lt;a href='http://typica.s3.amazonaws.com/index.html'&gt;online&lt;/a&gt;.  The application connects to the Amazon SimpleDB service by means of the &lt;em&gt;SimpleDB(accessIdString, secretKeyString)&lt;/em&gt; constructor.  It then creates a new domain by called the &lt;em&gt;createDomain(nameString)&lt;/em&gt; method.  Any Typica SimpleDB exceptions are handled by the &lt;em&gt;SDBException()&lt;/em&gt; exceptions constructor.  &lt;br /&gt;&lt;br /&gt;If you plan to use this example and the subsequent examples with the M/DB service, you will need to modify the &lt;em&gt;SimpleDB&lt;/em&gt; constructor to supply the server host string and possibly the port number.  See the Typica SimpleDB class documentation for further information.&lt;br /&gt;&lt;br /&gt;Here is the output. when compiled and run.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ javac SDBexample.java&lt;br /&gt;$ java SDBexample&lt;br /&gt;created example domain&lt;br /&gt;$&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;For our next example, we will create two SimpleDB domains, list all our domains, and delete the domains.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;&lt;br /&gt;import com.xerox.amazonws.sdb.Domain;&lt;br /&gt;import com.xerox.amazonws.sdb.ListDomainsResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBException;&lt;br /&gt;import com.xerox.amazonws.sdb.SimpleDB;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class SDBexample1 {&lt;br /&gt;&lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;      // NOTE - replace AAA with your access key and SSS with your secret key&lt;br /&gt;      SimpleDB simpleDB = new SimpleDB("AAA","SSS");&lt;br /&gt;&lt;br /&gt;      try {&lt;br /&gt;          simpleDB.createDomain("example1");&lt;br /&gt;          System.out.println("created example1 domain");&lt;br /&gt;&lt;br /&gt;          simpleDB.createDomain("example2");&lt;br /&gt;          System.out.println("created example2 domain");&lt;br /&gt;&lt;br /&gt;          ListDomainsResult list = simpleDB.listDomains();&lt;br /&gt;&lt;br /&gt;          Iterator iterator = list.getDomainList().iterator();&lt;br /&gt;          while (iterator.hasNext())&lt;br /&gt;          {&lt;br /&gt;              Domain domain = (Domain) iterator.next();&lt;br /&gt;              System.out.println("List domain: " + domain.getName());&lt;br /&gt;              simpleDB.deleteDomain(domain.getName());&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          System.out.println("deleted all domains");&lt;br /&gt;      } catch (SDBException ex) {&lt;br /&gt;          System.err.println("message : " + ex.getMessage());&lt;br /&gt;          System.err.println("requestID : " + ex.getRequestId());&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;              System.err.println("Error occured: " + e.getMessage());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;It uses the &lt;em&gt;listDomains()&lt;/em&gt; method to return a list of all the current domains, the &lt;em&gt;getDomainList()&lt;/em&gt; to set up iteration of the returned list of domains and the &lt;em&gt;deleteDomain()&lt;/em&gt; method to delete a domain.&lt;br /&gt;&lt;br /&gt;Here the the output from running this example.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;created example1 domain&lt;br /&gt;created example2 domain&lt;br /&gt;List domain: example&lt;br /&gt;List domain: example1&lt;br /&gt;List domain: example2&lt;br /&gt;deleted all domains&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Note that it listed and deleted the &lt;em&gt;example&lt;/em&gt; domain which we created in the previous example.&lt;br /&gt;&lt;br /&gt;In the next example we use a properties file &lt;em&gt;aws.properties&lt;/em&gt; to store the AWS &lt;em&gt;accessid&lt;/em&gt; and &lt;em&gt;secretkey&lt;/em&gt; strings. We encrypt communications between the application and AWS by adding a third parameter &lt;em&gt;true&lt;/em&gt; to the &lt;em&gt;SimpleDB()&lt;/em&gt; constructor.  We also retrieve and print out the domain metadata.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.FileNotFoundException;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;&lt;br /&gt;import com.xerox.amazonws.sdb.Domain;&lt;br /&gt;import com.xerox.amazonws.sdb.DomainMetadataResult;&lt;br /&gt;import com.xerox.amazonws.sdb.ListDomainsResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBException;&lt;br /&gt;import com.xerox.amazonws.sdb.SimpleDB;&lt;br /&gt;&lt;br /&gt;public class SDBexample3 {&lt;br /&gt;   private static String AWS_PROPERTIES = "aws.properties";&lt;br /&gt;   private static String AWS_ACCESSID = "aws.accessId";&lt;br /&gt;   private static String AWS_SECRETKEY = "aws.secretKey";&lt;br /&gt;&lt;br /&gt;   private static String domainName = "test1";&lt;br /&gt;   private static String awsAccessId = null;&lt;br /&gt;   private static String awsSecretKey = null;&lt;br /&gt;&lt;br /&gt;   private static Properties props;&lt;br /&gt;&lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;      /* get the accessid and secretkey strings from the properties file*/&lt;br /&gt;      try {&lt;br /&gt;           props = new Properties();&lt;br /&gt;           props.load(new FileInputStream(AWS_PROPERTIES));&lt;br /&gt;&lt;br /&gt;           awsAccessId = props.getProperty(AWS_ACCESSID);&lt;br /&gt;           if (awsAccessId == null || awsAccessId.trim().length() == 0)&lt;br /&gt;           {&lt;br /&gt;               System.out.println("Access key found or not set");&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;           }&lt;br /&gt;           awsSecretKey = props.getProperty(AWS_SECRETKEY);&lt;br /&gt;           if (awsSecretKey == null || awsSecretKey.trim().length() == 0)&lt;br /&gt;           {&lt;br /&gt;               System.out.println("Secret key either not found or not set");&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;           }&lt;br /&gt;       } catch (FileNotFoundException e) {&lt;br /&gt;          System.err.println("Could not find properties file");&lt;br /&gt;          System.exit((int) 1);&lt;br /&gt;       } catch (IOException e) {&lt;br /&gt;          System.err.println("Could not access properties file");&lt;br /&gt;          System.exit((int) 1);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;      /* encrypt communications */&lt;br /&gt;      SimpleDB simpleDB = new SimpleDB(awsAccessId, awsSecretKey, true);&lt;br /&gt;      try {&lt;br /&gt;          simpleDB.createDomain(domainName);&lt;br /&gt;          System.out.println("created " + domainName +  " domain");&lt;br /&gt;&lt;br /&gt;          ListDomainsResult list = simpleDB.listDomains();&lt;br /&gt;&lt;br /&gt;          Iterator iterator = list.getDomainList().iterator();&lt;br /&gt;          while (iterator.hasNext())&lt;br /&gt;          {&lt;br /&gt;              Domain domain = (Domain) iterator.next();&lt;br /&gt;              DomainMetadataResult metadata = domain.getMetadata();&lt;br /&gt;&lt;br /&gt;              System.out.println("\nDomain Metadata for : " + domain.getName());&lt;br /&gt;              System.out.println("     ItemCount: " + metadata.getItemCount());&lt;br /&gt;              System.out.println("     AttributeNameCount: " + metadata.getAttributeNameCount());&lt;br /&gt;              System.out.println("     AttributeValueCount: " + metadata.getAttributeValueCount());&lt;br /&gt;              System.out.println("     ItemNamesSizeBytes: " + metadata.getItemNamesSizeBytes());&lt;br /&gt;              System.out.println("     AttributeNamesSizeBytes: " + metadata.getAttributeNamesSizeBytes());&lt;br /&gt;              System.out.println("     AttributeValuesSizeBytes: " + metadata.getAttributeValuesSizeBytes());&lt;br /&gt;              System.out.println("     Timestamp: " + metadata.getTimestamp() + "\n");&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          simpleDB.deleteDomain(domainName);&lt;br /&gt;          System.out.println("deleted " + domainName + " domain");&lt;br /&gt;      } catch (SDBException ex) {&lt;br /&gt;          System.err.println("message : " + ex.getMessage());&lt;br /&gt;          System.err.println("requestID : " + ex.getRequestId());&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;              System.err.println("Error occured: " + e.getMessage());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here the the output from running this example. Note that most of the values are zero because we have not yet added any items or attributes.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;created test1 domain&lt;br /&gt;&lt;br /&gt;Domain Metadata for : test1&lt;br /&gt;     ItemCount: 0&lt;br /&gt;     AttributeNameCount: 0&lt;br /&gt;     AttributeValueCount: 0&lt;br /&gt;     ItemNamesSizeBytes: 0&lt;br /&gt;     AttributeNamesSizeBytes: 0&lt;br /&gt;     AttributeValuesSizeBytes: 0&lt;br /&gt;     Timestamp: Sat Aug 08 19:18:28 GMT-05:00 2009&lt;br /&gt;&lt;br /&gt;deleted test1 domain&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The next example is our first example to get (create) an &lt;em&gt;item&lt;/em&gt; using the &lt;em&gt;getItem()&lt;/em&gt; method and add &lt;em&gt;attributes&lt;/em&gt; to that &lt;em&gt;item&lt;/em&gt; using the &lt;em&gt;putAttrributes()&lt;/em&gt; method.  It includes a 2 second delay (sleep)  to guard against the &lt;em&gt;eventual consistency&lt;/em&gt; issue before attempting to retrieve the domain metadata. I found that a Java exception was sometimes thrown unless I added this delay. The delay I picked was arbitrary; a smaller delay may suffice.  It also includes a different way of retrieving the &lt;em&gt;accessid&lt;/em&gt; and &lt;em&gt;secretkey&lt;/em&gt; strings using &lt;em&gt;getClassLoader()&lt;/em&gt;.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import com.xerox.amazonws.sdb.Item;&lt;br /&gt;import com.xerox.amazonws.sdb.ItemAttribute;&lt;br /&gt;import com.xerox.amazonws.sdb.Domain;&lt;br /&gt;import com.xerox.amazonws.sdb.DomainMetadataResult;&lt;br /&gt;import com.xerox.amazonws.sdb.ListDomainsResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBException;&lt;br /&gt;import com.xerox.amazonws.sdb.SimpleDB;&lt;br /&gt;&lt;br /&gt;public class SDBexample4 {&lt;br /&gt;   private static String AWS_PROPERTIES = "aws.properties";&lt;br /&gt;   private static String AWS_ACCESSID = "aws.accessId";&lt;br /&gt;   private static String AWS_SECRETKEY = "aws.secretKey";&lt;br /&gt;&lt;br /&gt;   private static String domainName = "test4";&lt;br /&gt;&lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt;      try {&lt;br /&gt;           /* get the accessid and secretkey strings from the properties file*/&lt;br /&gt;           Properties props = new Properties();&lt;br /&gt;           props.load(SDBexample4.class.getClassLoader().getResourceAsStream(AWS_PROPERTIES));&lt;br /&gt;&lt;br /&gt;           String awsAccessId = props.getProperty(AWS_ACCESSID);&lt;br /&gt;           String awsSecretKey = props.getProperty(AWS_SECRETKEY);&lt;br /&gt;&lt;br /&gt;           if ((awsAccessId == null || awsAccessId.trim().length() == 0) ||&lt;br /&gt;               (awsSecretKey == null || awsSecretKey.trim().length() == 0))&lt;br /&gt;           {&lt;br /&gt;               System.out.println("Either access key or Secret key not found or not set");&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;           }&lt;br /&gt;          SimpleDB simpleDB = new SimpleDB(awsAccessId, awsSecretKey, true);&lt;br /&gt;&lt;br /&gt;          Domain dom = simpleDB.createDomain(domainName);&lt;br /&gt;          System.out.println("created " + dom.getName() +  " domain");&lt;br /&gt;&lt;br /&gt;          // new item (called 'xset1')&lt;br /&gt;          Item i = dom.getItem("xset1");&lt;br /&gt;&lt;br /&gt;          List&lt;ItemAttribute&gt; list = new ArrayList&lt;ItemAttribute&gt;();&lt;br /&gt;&lt;br /&gt;          list.add(new ItemAttribute("test1", "value1", false));&lt;br /&gt;          list.add(new ItemAttribute("test2", "value2", false));&lt;br /&gt;          list.add(new ItemAttribute("test3", "value3", false));&lt;br /&gt;&lt;br /&gt;          // add the 3 attributes to xset1&lt;br /&gt;          i.putAttributes(list);&lt;br /&gt;&lt;br /&gt;          // sleep for 2 seconds to handle "eventual consistency'&lt;br /&gt;          Long stoptime = 2000L;&lt;br /&gt;          System.out.print("going to sleep for 2 seconds ");&lt;br /&gt;          try {&lt;br /&gt;              Thread.sleep(stoptime);&lt;br /&gt;          } catch (InterruptedException e) {&lt;br /&gt;               e.printStackTrace();&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;          }&lt;br /&gt;          System.out.println("Done!");&lt;br /&gt;&lt;br /&gt;          // get the domain metadata&lt;br /&gt;          DomainMetadataResult metadata = dom.getMetadata();&lt;br /&gt;&lt;br /&gt;          System.out.println("\nDomain Metadata for : " + dom.getName());&lt;br /&gt;          System.out.println("     ItemCount: " + metadata.getItemCount());&lt;br /&gt;          System.out.println("     AttributeNameCount: " + metadata.getAttributeNameCount());&lt;br /&gt;          System.out.println("     AttributeValueCount: " + metadata.getAttributeValueCount());&lt;br /&gt;          System.out.println("     ItemNamesSizeBytes: " + metadata.getItemNamesSizeBytes());&lt;br /&gt;          System.out.println("     AttributeNamesSizeBytes: " + metadata.getAttributeNamesSizeBytes());&lt;br /&gt;          System.out.println("     AttributeValuesSizeBytes: " + metadata.getAttributeValuesSizeBytes());&lt;br /&gt;          System.out.println("     Timestamp: " + metadata.getTimestamp() + "\n");&lt;br /&gt;&lt;br /&gt;          simpleDB.deleteDomain(domainName);&lt;br /&gt;          System.out.println("deleted " + domainName + " domain");&lt;br /&gt;      } catch (SDBException ex) {&lt;br /&gt;          System.err.println("message : " + ex.getMessage());&lt;br /&gt;          System.err.println("requestID : " + ex.getRequestId());&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;              System.err.println("Error occured: " + e.getMessage());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output for this example:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;created test5 domain&lt;br /&gt;going to sleep for 2 seconds Done!&lt;br /&gt;&lt;br /&gt;Domain Metadata for : test4&lt;br /&gt;     ItemCount: 1&lt;br /&gt;     AttributeNameCount: 3&lt;br /&gt;     AttributeValueCount: 3&lt;br /&gt;     ItemNamesSizeBytes: 5&lt;br /&gt;     AttributeNamesSizeBytes: 15&lt;br /&gt;     AttributeValuesSizeBytes: 18&lt;br /&gt;     Timestamp: Sat Aug 08 21:48:07 GMT-05:00 2009&lt;br /&gt;&lt;br /&gt;deleted test5 domain&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The next example creates two items (&lt;em&gt;xset1&lt;/em&gt; and &lt;em&gt;xset2&lt;/em&gt;) and adds 10 attributes to each item. It also outputs the &lt;em&gt;request identifier&lt;/em&gt; and &lt;em&gt;box usage&lt;/em&gt; for each of the two &lt;em&gt;putAttributes&lt;/em&gt; requests.  Every request generates a response message and these two items are included as part of this message.  Box usage is the measure of machine resources consumed by a request.  It does not include bandwidth or storage. It is reported as the portion of a machine hour used to complete a particular request. &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import com.xerox.amazonws.sdb.Item;&lt;br /&gt;import com.xerox.amazonws.sdb.ItemAttribute;&lt;br /&gt;import com.xerox.amazonws.sdb.Domain;&lt;br /&gt;import com.xerox.amazonws.sdb.DomainMetadataResult;&lt;br /&gt;import com.xerox.amazonws.sdb.ListDomainsResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBException;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SimpleDB;&lt;br /&gt;&lt;br /&gt;public class SDBexample5 {&lt;br /&gt;   private static String AWS_PROPERTIES = "aws.properties";&lt;br /&gt;   private static String AWS_ACCESSID = "aws.accessId";&lt;br /&gt;   private static String AWS_SECRETKEY = "aws.secretKey";&lt;br /&gt;&lt;br /&gt;   private static String domainName = "test5";&lt;br /&gt;&lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;     try {&lt;br /&gt;&lt;br /&gt;           /* get the accessid and secretkey strings from the properties file*/&lt;br /&gt;           Properties props = new Properties();&lt;br /&gt;           props.load(SDBexample4.class.getClassLoader().getResourceAsStream(AWS_PROPERTIES));&lt;br /&gt;&lt;br /&gt;           String awsAccessId = props.getProperty(AWS_ACCESSID);&lt;br /&gt;           String awsSecretKey = props.getProperty(AWS_SECRETKEY);&lt;br /&gt;&lt;br /&gt;           if ((awsAccessId == null || awsAccessId.trim().length() == 0) ||&lt;br /&gt;               (awsSecretKey == null || awsSecretKey.trim().length() == 0))&lt;br /&gt;           {&lt;br /&gt;               System.out.println("Either access key or Secret key not found or not set");&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;          SimpleDB simpleDB = new SimpleDB(awsAccessId, awsSecretKey, true);&lt;br /&gt;&lt;br /&gt;          Domain dom = simpleDB.createDomain(domainName);&lt;br /&gt;          System.out.println("created " + dom.getName() +  " domain");&lt;br /&gt;&lt;br /&gt;          Item i = dom.getItem("xset1");&lt;br /&gt;&lt;br /&gt;          List&lt;ItemAttribute&gt; list = new ArrayList&lt;ItemAttribute&gt;();&lt;br /&gt;&lt;br /&gt;          list.add(new ItemAttribute("test10", "value10", false));&lt;br /&gt;          list.add(new ItemAttribute("test11", "value11", false));&lt;br /&gt;          list.add(new ItemAttribute("test12", "value12", false));&lt;br /&gt;          list.add(new ItemAttribute("test13", "value13", false));&lt;br /&gt;          list.add(new ItemAttribute("test14", "value14", false));&lt;br /&gt;          list.add(new ItemAttribute("test15", "value15", false));&lt;br /&gt;          list.add(new ItemAttribute("test16", "value16", false));&lt;br /&gt;          list.add(new ItemAttribute("test17", "value17", false));&lt;br /&gt;          list.add(new ItemAttribute("test18", "value18", false));&lt;br /&gt;          list.add(new ItemAttribute("test19", "value19", false));&lt;br /&gt;&lt;br /&gt;          SDBResult result = i.putAttributes(list);&lt;br /&gt;          System.out.println("Item Identifier: " + i.getIdentifier());&lt;br /&gt;          System.out.println("     Request ID: " + result.getRequestId());&lt;br /&gt;          System.out.println("      Box Usage: " + result.getBoxUsage());&lt;br /&gt;          i = dom.getItem("xset2");&lt;br /&gt;          list = new ArrayList&lt;ItemAttribute&gt;();&lt;br /&gt;&lt;br /&gt;          list.add(new ItemAttribute("test20", "value20", false));&lt;br /&gt;          list.add(new ItemAttribute("test21", "value21", false));&lt;br /&gt;          list.add(new ItemAttribute("test22", "value22", false));&lt;br /&gt;          list.add(new ItemAttribute("test23", "value23", false));&lt;br /&gt;          list.add(new ItemAttribute("test24", "value24", false));&lt;br /&gt;          list.add(new ItemAttribute("test25", "value25", false));&lt;br /&gt;          list.add(new ItemAttribute("test26", "value26", false));&lt;br /&gt;          list.add(new ItemAttribute("test27", "value27", false));&lt;br /&gt;          list.add(new ItemAttribute("test28", "value28", false));&lt;br /&gt;          list.add(new ItemAttribute("test29", "value29", false));&lt;br /&gt;&lt;br /&gt;          result = i.putAttributes(list);&lt;br /&gt;          System.out.println("Item Identifier: " + i.getIdentifier());&lt;br /&gt;          System.out.println("     Request ID: " + result.getRequestId());&lt;br /&gt;          System.out.println("      Box Usage: " + result.getBoxUsage());&lt;br /&gt;&lt;br /&gt;          // sleep for 2 seconds to handle "eventual consistency'&lt;br /&gt;          Long stoptime = 2000L;&lt;br /&gt;          System.out.print("going to sleep for 2 seconds ");&lt;br /&gt;          try {&lt;br /&gt;              Thread.sleep(stoptime);&lt;br /&gt;          } catch (InterruptedException e) {&lt;br /&gt;               e.printStackTrace();&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;          }&lt;br /&gt;          System.out.println("Done!");&lt;br /&gt; &lt;br /&gt;          ListDomainsResult list1 = simpleDB.listDomains();&lt;br /&gt;          Iterator iterator = list1.getDomainList().iterator();&lt;br /&gt;          while (iterator.hasNext())&lt;br /&gt;          {&lt;br /&gt;              Domain domain = (Domain) iterator.next();&lt;br /&gt;              DomainMetadataResult metadata = domain.getMetadata();&lt;br /&gt;&lt;br /&gt;              System.out.println("\nDomain Metadata for : " + domain.getName());&lt;br /&gt;              System.out.println("     ItemCount: " + metadata.getItemCount());&lt;br /&gt;              System.out.println("     AttributeNameCount: " + metadata.getAttributeNameCount());&lt;br /&gt;              System.out.println("     AttributeValueCount: " + metadata.getAttributeValueCount());&lt;br /&gt;              System.out.println("     ItemNamesSizeBytes: " + metadata.getItemNamesSizeBytes());&lt;br /&gt;              System.out.println("     AttributeNamesSizeBytes: " + metadata.getAttributeNamesSizeBytes());&lt;br /&gt;              System.out.println("     AttributeValuesSizeBytes: " + metadata.getAttributeValuesSizeBytes());&lt;br /&gt;              System.out.println("     Timestamp: " + metadata.getTimestamp() + "\n");&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;      } catch (SDBException ex) {&lt;br /&gt;          System.err.println("message : " + ex.getMessage());&lt;br /&gt;          System.err.println("requestID : " + ex.getRequestId());&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;              System.err.println("Error occured: " + e.getMessage());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output for this example:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;created test5 domain&lt;br /&gt;Item Identifier: xset1&lt;br /&gt;     Request ID: 34e6df86-5f2b-4bcf-312d-22b595a87fe7&lt;br /&gt;      Box Usage: 0.0000221907&lt;br /&gt;Item Identifier: xset2&lt;br /&gt;     Request ID: dd66f222-de70-3d06-8ce5-7842e5d22d1d&lt;br /&gt;      Box Usage: 0.0000221907&lt;br /&gt;going to sleep for 4 seconds Done!&lt;br /&gt;&lt;br /&gt;Domain Metadata for : test5&lt;br /&gt;     ItemCount: 2&lt;br /&gt;     AttributeNameCount: 20&lt;br /&gt;     AttributeValueCount: 20&lt;br /&gt;     ItemNamesSizeBytes: 10&lt;br /&gt;     AttributeNamesSizeBytes: 120&lt;br /&gt;     AttributeValuesSizeBytes: 140&lt;br /&gt;     Timestamp: Sun Aug 09 08:44:19 GMT-05:00 2009&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;For our final example, we will retrieve and print the attributes stored in the &lt;em&gt;test5&lt;/em&gt; domain &lt;em&gt;xset1&lt;/em&gt; item by the previous example.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import com.xerox.amazonws.sdb.Item;&lt;br /&gt;import com.xerox.amazonws.sdb.ItemAttribute;&lt;br /&gt;import com.xerox.amazonws.sdb.Domain;&lt;br /&gt;import com.xerox.amazonws.sdb.DomainMetadataResult;&lt;br /&gt;import com.xerox.amazonws.sdb.ListDomainsResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBException;&lt;br /&gt;import com.xerox.amazonws.sdb.SDBResult;&lt;br /&gt;import com.xerox.amazonws.sdb.SimpleDB;&lt;br /&gt;&lt;br /&gt;public class SDBexample6 {&lt;br /&gt;   private static String AWS_PROPERTIES = "aws.properties";&lt;br /&gt;   private static String AWS_ACCESSID = "aws.accessId";&lt;br /&gt;   private static String AWS_SECRETKEY = "aws.secretKey";&lt;br /&gt;&lt;br /&gt;   private static String domainName = "test5";&lt;br /&gt;&lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt;      try {&lt;br /&gt;&lt;br /&gt;           /* get the accessid and secretkey strings from the properties file*/&lt;br /&gt;           Properties props = new Properties();&lt;br /&gt;           props.load(SDBexample4.class.getClassLoader().getResourceAsStream(AWS_PROPERTIES));&lt;br /&gt;&lt;br /&gt;           String awsAccessId = props.getProperty(AWS_ACCESSID);&lt;br /&gt;           String awsSecretKey = props.getProperty(AWS_SECRETKEY);&lt;br /&gt;          if ((awsAccessId == null || awsAccessId.trim().length() == 0) ||&lt;br /&gt;               (awsSecretKey == null || awsSecretKey.trim().length() == 0))&lt;br /&gt;           {&lt;br /&gt;               System.out.println("Either access key or Secret key not found or not set");&lt;br /&gt;               System.exit((int) 1);&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;          SimpleDB simpleDB = new SimpleDB(awsAccessId, awsSecretKey, true);&lt;br /&gt;&lt;br /&gt;          Domain dom = simpleDB.getDomain(domainName);&lt;br /&gt;          System.out.println("opened " + dom.getName() +  " domain");&lt;br /&gt;&lt;br /&gt;          Item i = dom.getItem("xset1");&lt;br /&gt;&lt;br /&gt;          List&lt;ItemAttribute&gt; attrs = i.getAttributes();&lt;br /&gt;          for (ItemAttribute attr : attrs) {&lt;br /&gt;              System.out.println(attr.getName() + " = " + attr.getValue());&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;      } catch (SDBException ex) {&lt;br /&gt;          System.err.println("message : " + ex.getMessage());&lt;br /&gt;          System.err.println("requestID : " + ex.getRequestId());&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;              System.err.println("Error occured: " + e.getMessage());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output from this example:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;opened test5 domain&lt;br /&gt;test10 = value10&lt;br /&gt;test12 = value12&lt;br /&gt;test11 = value11&lt;br /&gt;test14 = value14&lt;br /&gt;test13 = value13&lt;br /&gt;test16 = value16&lt;br /&gt;test15 = value15&lt;br /&gt;test18 = value18&lt;br /&gt;test17 = value17&lt;br /&gt;test19 = value19&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Well that is all of the examples for now.  If you compile, run and play with these examples, you should end up with a good understanding of how to use the Typica library to access and manipulate Amazon SimpleDB.  I plan to discuss how to query Amazon SimpleDB using this library in a future post.&lt;br /&gt;&lt;br /&gt;Can the Typica library be used as part of a AWS Cloud VIM implementation?  Absolutely.  Can Amazon SimpleDB be used to implement a Cloud XAM Storage System?  Not by itself.  However if Amazon S3 is used to provide persistence for XStreams and Amazon SimpleDB is used to provide persistence for XSet metadata, the answer is yes to a basic prototype of a Cloud XAM Storage System but no for a production quality Cloud XAM Storage System due the &lt;em&gt;eventual consistency&lt;/em&gt; issue as well as the current limitations in the number of attributes, size of domains, no datatyping and seconds a query may run.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-5050592230189845572?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/5050592230189845572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/08/amazon-simpledb-typica-tutorial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/5050592230189845572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/5050592230189845572'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/08/amazon-simpledb-typica-tutorial.html' title='Amazon SimpleDB Typica Tutorial'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-6060261547235990067</id><published>2009-07-19T23:59:00.000-04:00</published><updated>2009-08-22T00:00:46.036-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='SNIA'/><category scheme='http://www.blogger.com/atom/ns#' term='XAM'/><title type='text'>XAM Query Language</title><content type='html'>As well as providing vendor-independent means of creating, retrieving, modifying and deleting XSets, the SNIA &lt;a href="http://www.snia.org/forums/xam/technology/specs/"&gt;XAM v1.0&lt;/a&gt; specification also defines a query language (XAM QL), based on a subset of the &lt;a href="http://en.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt; language, for selecting and retrieving the XUIDs of XSets based on content-defined criteria.&lt;br /&gt;&lt;br /&gt;The set of reserved words for this query language is quite small: &lt;em&gt;select&lt;/em&gt;, &lt;em&gt;where&lt;/em&gt;, &lt;em&gt;and&lt;/em&gt;, &lt;em&gt;or&lt;/em&gt;, &lt;em&gt;not&lt;/em&gt;, &lt;em&gt;like&lt;/em&gt;, &lt;em&gt;exists&lt;/em&gt;, &lt;em&gt;binding&lt;/em&gt;, &lt;em&gt;readonly&lt;/em&gt;, &lt;em&gt;typeof&lt;/em&gt;, &lt;em&gt;length&lt;/em&gt;, &lt;em&gt;date&lt;/em&gt;, &lt;em&gt;TRUE&lt;/em&gt;, &lt;em&gt;FALSE&lt;/em&gt;, &lt;em&gt;before&lt;/em&gt;, &lt;em&gt;after&lt;/em&gt;, &lt;em&gt;contains&lt;/em&gt;, and &lt;em&gt;within&lt;/em&gt;. By design, XAM queries look like an SQL &lt;em&gt;select&lt;/em&gt; statement.  The query language is case insensitive and uses the ASCII character set.  &lt;br /&gt;&lt;br /&gt;Here is an example of a simple XAM query:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where "com.example.name" = ’Tuckers Plantation'&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Version 1.0 of the XAM specification defines two levels of query language support, i.e. &lt;em&gt;Level 1&lt;/em&gt; and &lt;em&gt;Level 2&lt;/em&gt;.  Level 1 defines queries on properties and field attributes in XSets and is mandatory.  Any XSet property value that is accessible to an application program via the XAM library can be queried.  Level 2 extends Level 1 to support queries on XStreams and is optional.  Both levels of query are accessed through a single, defined job type that all XAM providers must support.  Since no vendor that I am aware of has actually implemented level 2 queries, the remainder of this post focuses on level 1 queries.&lt;br /&gt;&lt;br /&gt;A XAM query statement consists of a mandatory &lt;em&gt;select&lt;/em&gt; clause followed by an optional &lt;em&gt;where&lt;/em&gt; clause.  For XAM v1.0 the only valid select clause is &lt;em&gt;select '.xset.xuid'&lt;/em&gt;.  This specifies that the application is requesting a list of XUID values.  For example&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid "&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;will return a list of every XSet that is readable at the time of the query.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;where&lt;/em&gt; clause is used to specify a subset of XSets to be matched.  For level 1 queries it is restricted to comparisons between XSet properties and literal values and/or field attributes and literal values.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where ".xam.time.xuid" &amp;gt; date(’2009-02-01T00:00:00.0’)&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;will return the list of all Xsets which were created on or after February 1st 2009.&lt;br /&gt;&lt;br /&gt;The following table shows which field and literal types can be validly compared.&lt;br /&gt;[table id=14/]&lt;br /&gt;The XAM library validates that strings and strings liberals are conforming UTF-8 strings. Non-conforming UTF-8 string literals generate a XAM non-fatal query syntax error. Issues such as single versus multiple glyph characters and non printable characters are unspecified and are implementation and application dependent. String comparisons are case sensitive and comparison operators operate on a byte-by-byte basis.  For relational operators the relationships are defined by the byte values. All data normalization is the responsibility of the application.&lt;br /&gt;&lt;br /&gt;The supported escape sequences are the following. Any other escape sequence will generate an non-fatal error.&lt;br /&gt;[table id=15/]&lt;br /&gt;String literals must be quoted with single quotes. String literals which contain one or more single quote characters must escape each single quote character using a backslash. For example, the string literal of ’This is a string literal’ would be represented in a query as&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where "com.example.string-property" = ’This is a string literal’&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;To use a single quote in a string, guard it with a backslash&lt;br /&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;!--skip translation--&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where "com.example.claimed.ownership" = ’Tucker\’s’&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;All instances of field names in a XAM query string must be quoted with double quotes. If a field name contains double quote characters, each double quote character must be escaped using a backslash. For example, the field name for the &lt;em&gt;xam_boolean&lt;/em&gt; property &lt;em&gt;com.example.”qstring”&lt;/em&gt; should be represented in a query as&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xam.xuid" where "com.example.\"qstring\"" = TRUE&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;If a field name contains a backslash character, the backslash itself must be escaped with another backslash. For example, the field name for the &lt;em&gt;xam_double&lt;/em&gt; property &lt;em&gt;com.example.file\ratio&lt;/em&gt; should be represented in a query as&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xam.xuid" where "com.example.file\\ratio" = 100.1&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The query language accepts date-time and XUID-valued literals using the selector functions &lt;em&gt;date()&lt;/em&gt; and &lt;em&gt;xuid()&lt;/em&gt; respectively.  The &lt;em&gt;date()&lt;/em&gt; function takes a properly formed date-time value, specified as a literal string which is consistent with the XAM date-time specification.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where ".xam.time.xuid" = date(’2009-06-01T00:00:00.0’)&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The &lt;em&gt;xuid()&lt;/em&gt; function expects an XUID which is in the form of a base64 encoded string literal.  An improperly formed string literal generates a non-fatal error during query parsing.&lt;br /&gt;&lt;br /&gt;Field attributes are accessed using the &lt;em&gt;exists&lt;/em&gt;, &lt;em&gt;typeof&lt;/em&gt;, &lt;em&gt;readonly&lt;/em&gt;, &lt;em&gt;binding&lt;/em&gt;, and &lt;em&gt;length&lt;/em&gt; field attribute accessor functions. The &lt;em&gt;exists()&lt;/em&gt; function tests for the existence of an named field attribute (property) in an XSet. It evaluates to TRUE if an XSet contains the named field otherwise it evaluates FALSE.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where exists("com.example.name")&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The &lt;em&gt;typeof()&lt;/em&gt; function returns the MIME type of a named field in an XSet which is a string-valued property.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where typeof("com.example.data") = ’text/plain’&lt;br /&gt;select ".xset.xuid" where typeof("com.example.data") like ’text%’&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;This function can be used whenever an application could use a field reference to a string-valued property. Note that comparisons with any non-string literal value generate a non-fatal error during the parsing of the query.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;readonly()&lt;/em&gt; function evaluates to TRUE when a field in an XSet is marked as readonly.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where readonly("com.example.flag")&lt;br /&gt;select ".xset.xuid" where not readonly("com.example.name")&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The &lt;em&gt;binding()&lt;/em&gt; function evaluates to TRUE when a field in an XSet is marked as binding.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where binding("com.example.case_id")&lt;br /&gt;select ".xset.xuid" where not binding("com.example.subject")&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The length() function returns the length, in bytes, of a named field. &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where length("com.example.data") &amp;gt; 1024&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;When used on property fields this function returns the length as defined for &lt;em&gt;stypes&lt;/em&gt;.  Note that this function should not be used to compare the number of characters in a string as this comparison depends on the character encoding being used.&lt;br /&gt;&lt;br /&gt;Turning now to logical operators.  Subclauses within the &lt;em&gt;where&lt;/em&gt; clause may be combined and modified by using the logical operators &lt;em&gt;and&lt;/em&gt;, &lt;em&gt;or&lt;/em&gt; and &lt;em&gt;not&lt;/em&gt;. These operators are similar to their SQL counterparts.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;and&lt;/em&gt; operator requires both subclauses to evaluate to TRUE before including an XSet in the results. For example&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where typeof("com.example.stream") = ’image/gif’ and length("com.example.stream") &amp;gt; 4096&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;selects only those XSets containing GIF images whose size is greater than 4096 bytes. The &lt;em&gt;or&lt;/em&gt; operator evaluates to TRUE if either subclause evaluates to TRUE. For example&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where typeof("com.example.stream") = ’image/jpeg’ or typeof("com.example.stream") = ’image/gif’&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;selects only those XSets containing a named stream of image type JPEG or GIF.  The &lt;em&gt;not&lt;/em&gt; operator negates a boolean expression. For example&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where not binding("com.example.property")&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;selects all XSets with the nonbinding property &lt;em&gt;com.example.property&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;As in SQL certain operators take precedence over other operators in queries. XAM QL operator precedence is as follows:&lt;br /&gt;[table id=16/]&lt;br /&gt;Operators of the same precedence are evaluated left to right within a query. However operator precedence may be overridden using parentheses as shown by the following example.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class="notranslate"&gt;&lt;br /&gt;&lt;pre class="displaybox"&gt;select ".xset.xuid" where not "com.example.bool-prop" and  "com.example.int-prop" = 64&lt;br /&gt;select ".xset.xuid" where not ("com.example.bool-prop" and "com.example.int-prop" = 64)&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;In the first example, the &lt;em&gt;not&lt;/em&gt; operator only applies to the &lt;em&gt;com.example.bool-prop&lt;/em&gt; property. In the second example, the &lt;em&gt;not&lt;/em&gt; operator applies to both &lt;em&gt;com.example.bool-prop&lt;/em&gt; and &lt;em&gt;com.example.int-prop = 42&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Now that we are somewhat familiar with XAM QL syntax, the next question to be answered is how do we tell a XAM Storage System to execute a query and return the results to us.  Well it turns out that a query is executed as a particular type of XAM job called a &lt;em&gt;query job&lt;/em&gt;. The input to a query job is an XSet which you must create. This XSet must contain two items - the field &lt;em&gt;org.snia.xam.job.command&lt;/em&gt; which is always set to 'xam.job.query' and a XStream &lt;em&gt;xam.job.query.command&lt;/em&gt; which is a UTF-8 text stream (MIME type 'text/plain; charset=utf-8’) containing the actual query expression string.&lt;br /&gt;&lt;br /&gt;A query job may optionally be committed before or during the execution of the job, but this commit is not required. The ability to commit a running job is optional and implementation dependant. An application can determine if job commit is supported by checking the XSystem boolean property &lt;em&gt;.xsystem.job.commit.supported&lt;/em&gt;.  Failure to commit a query job before closing the XSet means the results of the query job are not persistently stored.&lt;br /&gt;&lt;br /&gt;A query job is executed by invoking &lt;em&gt;submitJob&lt;/em&gt;.  If either of the two required items in the query job XSet  is not correctly filled in, the standard job error field &lt;em&gt;.xam.job.error&lt;/em&gt; is added to the query job XSet and it's value is set to either &lt;em&gt;org.snia.xam::not_a_job&lt;/em&gt; or  &lt;em&gt;org.snia.xam::unspecified_command&lt;/em&gt; and the query  job is aborted.  As shown in the sample application below, the state of a query job may be determined by examining the value of &lt;em&gt;.xam.job.status&lt;/em&gt;.  &lt;br /&gt;&lt;br /&gt;When a query job is successful, the results are stored in the query job XSet in the form of a new XStream named &lt;em&gt;xam.job.query.results&lt;/em&gt;. This XStream has a MIME type of &lt;em&gt;application/vnd.snia.xam.query.xuid_list&lt;/em&gt; and contains the XUIDs for the set of XSets resulting from the evaluation of the query.  Each XUID is stored in a binary format as part of an 80-byte record.  If an XUID is shorter than 80 bytes, the record is zero padded to 80 bytes.&lt;br /&gt;&lt;br /&gt;A number of other properties relating to the results XStream are also set up. The &lt;em&gt;xam_int&lt;/em&gt; property &lt;em&gt;xam.job.query.results.count&lt;/em&gt; contains the current count of the XUID records in the results XStream. This property is updated as results are entered into the results XStream during query processing.  An application can use this to provide status information to users as the query job executes.  The &lt;em&gt;xam_string&lt;/em&gt; property &lt;em&gt;xam.job.query.level&lt;/em&gt; indicates the query level which matches the results. Its value is either &lt;em&gt;org.snia.xam.job.query.level.1&lt;/em&gt; or &lt;em&gt;org.snia.xam.job.query.level.2&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;It is important to remember that a query job operates within the roles and permissions granted to the connection. That means the results XStream only includes those XSets that are visible and accessible to an application, at least from a read perspective, according to the role under which the query job is executed.&lt;br /&gt;&lt;br /&gt;The query job may set the following error codes in &lt;em&gt;.xam.job.error&lt;/em&gt;:&lt;br /&gt;[table id=17/]&lt;br /&gt;When a query job is halted for whatever reason, the standard job health and status fields, i.e &lt;em&gt;.xam.job.errorhealth&lt;/em&gt; and &lt;em&gt;.xam.job.status&lt;/em&gt;, are set to appropriate values and the XAM Storage System may place zero or more additional XUIDs in the results XStream.  Thus an application should always see complete XUID values in the results XStream.  Resuming a halted query job is not supported.&lt;br /&gt;&lt;br /&gt;Note that, unlike a traditional RDBMS, there is no locking of an XAM Storage System during the execution of a query job. Thus a query result is not an instantaneous snapshot of a XAM Storage System. The contents of a XAM Storage System may or may not change while a query job is executed. The general rule is that any XSet that has been stored before the start of the query job is included in the results XStream if it meets the query criteria, and any XSet that has been stored after the query job has completed is not be included in the results XStream. XSets that are stored during the query job execution may or may not be included. The same criteria applies to the results XStream. It may include XUIDs of XSets that are no longer in the XAM Storage System and XUIDs of XSets that no longer meet the search criteria due to a change in the XSet after the particular XSet was queried.&lt;br /&gt;&lt;br /&gt;Here is a simple Java application that queries an XAM Storage System to determine it's level of support for XAM queries.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import org.snia.xam.XAMException;&lt;br /&gt;import org.snia.xam.XAMLibrary;&lt;br /&gt;import org.snia.xam.XSystem;&lt;br /&gt;import org.snia.xam.toolkit.XAMXUID;&lt;br /&gt;import org.snia.xam.util.XAMLibraryFactory;&lt;br /&gt;&lt;br /&gt;public class CheckQuerySupport&lt;br /&gt;{&lt;br /&gt;    private static XAMLibrary xamLib;&lt;br /&gt;    private static XSystem xSystem;&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args)&lt;br /&gt;    {   &lt;br /&gt;        String xri = "snia-xam://centera_vim!XXX.XXXX.XXX.XXX?/home/fpm/xam/xamconnect.pea";&lt;br /&gt;&lt;br /&gt;        long exitCode = 0;&lt;br /&gt;        boolean isSupported = false;&lt;br /&gt;&lt;br /&gt;        try     &lt;br /&gt;        {       &lt;br /&gt;            xamLib = XAMLibraryFactory.newXAMLibrary();&lt;br /&gt;            System.out.println("Connecting to XSystem: " + xri + "\n");&lt;br /&gt;&lt;br /&gt;            xSystem = xamLib.connect(xri);&lt;br /&gt;&lt;br /&gt;            // support job commit?&lt;br /&gt;            isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_COMMIT_SUPPORTED);&lt;br /&gt;            System.out.println("Support job commit? " + (isSupported ? "Yes" : "No"));&lt;br /&gt;&lt;br /&gt;            // support continuance of job?&lt;br /&gt;            isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_QUERY_CONTINUANCE_SUPPORTED);&lt;br /&gt;            System.out.println("Support job continuance? " + (isSupported ? "Yes" : "No"));&lt;br /&gt;&lt;br /&gt;            // support level 1 query?&lt;br /&gt;            isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_QUERY_LEVEL1_SUPPORTED);&lt;br /&gt;            System.out.println("Support level 1 query? " + (isSupported ? "Yes" : "No"));&lt;br /&gt;&lt;br /&gt;            // support level 2 query?&lt;br /&gt;            isSupported = xSystem.getBoolean(XSystem.XAM_XSYSTEM_JOB_QUERY_LEVEL2_SUPPORTED);&lt;br /&gt;            System.out.println("Support level 2 query? " + (isSupported ? "Yes" : "No"));&lt;br /&gt;&lt;br /&gt;            xSystem.close();&lt;br /&gt;            System.out.println("\nClosed connection to XSystem");&lt;br /&gt;&lt;br /&gt;        } catch (XAMException xe) {&lt;br /&gt;            exitCode = xe.getStatusCode();&lt;br /&gt;            System.err.println("XAM Error occured: " + xe.getMessage());&lt;br /&gt;        } catch (IllegalArgumentException e) {&lt;br /&gt;            System.out.println(e.getMessage());&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;            exitCode = 1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        System.exit((int) exitCode);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output from this application when connected to an EMC Centera XAM Storage System&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;Connecting to XSystem: snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea&lt;br /&gt;&lt;br /&gt;Support job commit? No&lt;br /&gt;Support job continuance? No&lt;br /&gt;Support level 1 query? Yes&lt;br /&gt;Support level 2 query? No&lt;br /&gt;&lt;br /&gt;Closed connection to XSystem&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is a longer Java application that implements the three sample XSets and the sample queries which are discussed in section 10.8 of the XAM Architecture V1.0 document.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;&lt;br /&gt;import org.snia.xam.XAMException;&lt;br /&gt;import org.snia.xam.XAMLibrary;&lt;br /&gt;import org.snia.xam.XSet;&lt;br /&gt;import org.snia.xam.XStream;&lt;br /&gt;import org.snia.xam.XSystem;&lt;br /&gt;import org.snia.xam.XUID;&lt;br /&gt;import org.snia.xam.toolkit.XAMXUID;&lt;br /&gt;import org.snia.xam.util.XAMLibraryFactory;&lt;br /&gt;&lt;br /&gt;public class QueryExample&lt;br /&gt;{&lt;br /&gt;    private static XAMLibrary xamLib;&lt;br /&gt;    private static XSystem xSystem;&lt;br /&gt;&lt;br /&gt;    private static void CreateXset(int parm1, String parm2, double parm3)&lt;br /&gt;             throws XAMException&lt;br /&gt;    {&lt;br /&gt;        System.out.print("Create XSet 1 ....  ");&lt;br /&gt;&lt;br /&gt;        XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);&lt;br /&gt;        xSet.createProperty("com.example.rhc", false, true);&lt;br /&gt;        xSet.createProperty("com,example.foo", false, parm1);&lt;br /&gt;        xSet.createProperty("com.example.bar", false, parm2);&lt;br /&gt;        xSet.createProperty("com.example.num", false, parm3);&lt;br /&gt;&lt;br /&gt;        XUID xuID = xSet.commit();&lt;br /&gt;        System.out.println("XUID: " + xuID.toString());&lt;br /&gt;&lt;br /&gt;        xSet.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   private static void CreateXset(int parm1, int parm2, int parm3)&lt;br /&gt;             throws XAMException&lt;br /&gt;    {&lt;br /&gt;        System.out.print("Create XSet 2 ....  ");&lt;br /&gt;&lt;br /&gt;        XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);&lt;br /&gt;        xSet.createProperty("com.example.rhc", false, true);&lt;br /&gt;        xSet.createProperty("com,example.foo", false, parm1);&lt;br /&gt;        xSet.createProperty("com.example.bar", false, parm2);&lt;br /&gt;        xSet.createProperty("com.example.num", false, parm3);&lt;br /&gt;&lt;br /&gt;        XUID xuID = xSet.commit();&lt;br /&gt;        System.out.println("XUID: " + xuID.toString());&lt;br /&gt;&lt;br /&gt;        xSet.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static void CreateXset(int parm1, int parm2)&lt;br /&gt;             throws XAMException&lt;br /&gt;    {&lt;br /&gt;        System.out.print("Create XSet 3 ....  ");&lt;br /&gt;&lt;br /&gt;        XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);&lt;br /&gt;        xSet.createProperty("com.example.rhc", false, true);&lt;br /&gt;        xSet.createProperty("com,example.foo", false, parm1);&lt;br /&gt;        xSet.createProperty("com.example.num", false, parm2);&lt;br /&gt;&lt;br /&gt;        XUID xuID = xSet.commit();&lt;br /&gt;        System.out.println("XUID: " + xuID.toString());&lt;br /&gt;&lt;br /&gt;        xSet.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static void QueryXsystem(String queryString)&lt;br /&gt;            throws XAMException&lt;br /&gt;    {&lt;br /&gt;        boolean finished = false;&lt;br /&gt;        final int XAM_MAX_XUID = 80;&lt;br /&gt;        int resultCount = 0;&lt;br /&gt;        String status;&lt;br /&gt;&lt;br /&gt;        System.out.println("Create query XSet. Query string: " + queryString);&lt;br /&gt;&lt;br /&gt;        XSet query = xSystem.createXSet(XSet.MODE_UNRESTRICTED);&lt;br /&gt;        query.createProperty(XSet.XAM_JOB_COMMAND, true, XSet.XAM_JOB_QUERY);&lt;br /&gt;&lt;br /&gt;        byte[] buffer = queryString.getBytes();&lt;br /&gt;        XStream queryStream = query.createXStream(XSet.XAM_JOB_QUERY_COMMAND, true, XAMLibrary.TEXT_PLAIN_MIME_TYPE);&lt;br /&gt;        queryStream.write(buffer);&lt;br /&gt;        queryStream.close();&lt;br /&gt;&lt;br /&gt;        System.out.println("Submit query job ....");&lt;br /&gt;        query.submitJob();&lt;br /&gt;&lt;br /&gt;        System.out.println("Wait for query job to finish ....");&lt;br /&gt;&lt;br /&gt;        while (!finished)&lt;br /&gt;        {&lt;br /&gt;            // check  status of query job&lt;br /&gt;            status = query.getString(XSet.XAM_JOB_ERRORHEALTH);&lt;br /&gt;            if (status.equals(XSet.XAM_JOB_ERRORHEALTH_ERROR))&lt;br /&gt;            {&lt;br /&gt;                System.out.println("ERROR: Errorhealth - " + query.getString(XSet.XAM_JOB_ERROR));&lt;br /&gt;                query.haltJob();&lt;br /&gt;                System.out.println("ERROR: Job halted");&lt;br /&gt;                break;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            status = query.getString(XSet.XAM_JOB_STATUS);&lt;br /&gt;            resultCount = (int) query.getLong(XSet.XAM_JOB_QUERY_RESULTS_COUNT);&lt;br /&gt;&lt;br /&gt;            // uncomment if you want continuous job status &lt;br /&gt;            // System.out.println("Job Status: " + status + "  Result count: " + resultCount);&lt;br /&gt;&lt;br /&gt;            // exit loop if job complete &lt;br /&gt;            if (status.equals(XSet.XAM_JOB_STATUS_COMPLETE))&lt;br /&gt;            {&lt;br /&gt;                finished = true;&lt;br /&gt;            }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;        System.out.println("Query job completed ....");&lt;br /&gt;        System.out.println("Result set final count is: " + resultCount);&lt;br /&gt;&lt;br /&gt;        if (resultCount &gt; 0)&lt;br /&gt;        {&lt;br /&gt;             // open query job result stream&lt;br /&gt;             XStream results = query.openXStream(XSet.XAM_JOB_QUERY_RESULTS, XStream.MODE_READ_ONLY);&lt;br /&gt;&lt;br /&gt;             byte rawXUID[] = new byte[XAM_MAX_XUID];&lt;br /&gt;             long bytesRead = 0;&lt;br /&gt;&lt;br /&gt;             // output XUIDs in result set&lt;br /&gt;             while( (bytesRead = results.read(rawXUID, XAM_MAX_XUID)) &gt;= 0 )&lt;br /&gt;             {&lt;br /&gt;                 XAMXUID resultXUID = new XAMXUID(rawXUID);&lt;br /&gt;                 System.out.println("XUID: " + resultXUID.toString());&lt;br /&gt;             }&lt;br /&gt;&lt;br /&gt;             results.close();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        query.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args)&lt;br /&gt;    {&lt;br /&gt;        String xri = "snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea";&lt;br /&gt;        long exitCode = 0;&lt;br /&gt;&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            xamLib = XAMLibraryFactory.newXAMLibrary();&lt;br /&gt;&lt;br /&gt;            // uncomment next 2 lines if you want extensive XAM Library logging&lt;br /&gt;            // xamLib.setProperty(XAMLibrary.XAM_LOG_VERBOSITY, 1);&lt;br /&gt;            // xamLib.setProperty(XAMLibrary.XAM_LOG_LEVEL, 5);&lt;br /&gt;&lt;br /&gt;            System.out.println("Connecting to XSystem " +  xri + "\n");&lt;br /&gt;&lt;br /&gt;            xSystem = xamLib.connect(xri);&lt;br /&gt;            xSystem.setProperty(".xsystem.log.verbosity", 1);&lt;br /&gt;            xSystem.setProperty(".xsystem.log.level", 5);&lt;br /&gt;&lt;br /&gt;            CreateXset(1, "string", 123.55);&lt;br /&gt;            CreateXset(77, 42, 100);&lt;br /&gt;            CreateXset(6, 200);&lt;br /&gt;&lt;br /&gt;            xSystem.close();&lt;br /&gt;&lt;br /&gt;            System.out.println("\nClose/reopen XSystem\n");&lt;br /&gt;&lt;br /&gt;            xSystem = xamLib.connect(xri);&lt;br /&gt;&lt;br /&gt;            // uncomment one or more of the following queries&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\"");&lt;br /&gt;            QueryXsystem("select \".xset.xuid\" where (\"com.example.foo\" &gt; 0) and (\"com.example.foo\" &lt; 50)");&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\" where (\"com.example.bar\" &gt; 0) and (\"com.example.bar\" &lt; 100)");&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\" where exists (\"com.example.bar\")");&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\" where \"com.example.bar\" like '%ing%'");&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\" where \"com.example.num\" &gt;= 124");&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\" where \"com.example.num\" &gt;= 124.6 ");&lt;br /&gt;            // QueryXsystem("select \".xset.xuid\" where (\"com.example.num\" &gt;= 123) and typeof(\"com.example.num\") = 'application/vnd.snia.xam.int'");&lt;br /&gt;&lt;br /&gt;            xSystem.close();&lt;br /&gt;            System.out.println("\nClosed connection to XSystem");&lt;br /&gt;&lt;br /&gt;        } catch (XAMException xe) {&lt;br /&gt;            exitCode = xe.getStatusCode();&lt;br /&gt;            System.err.println("XAM Error occured: " + xe.getMessage() + "("&lt;br /&gt;                    + exitCode + ")");&lt;br /&gt;        } catch (IllegalArgumentException e) {&lt;br /&gt;            System.out.println(e.getMessage());&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;            exitCode = -1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        System.exit((int) exitCode);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Note that a results XStream produced by a query job may be consumed by an application before the XAM Storage System has finished storing all of the XUIDs in the results XStream if &lt;em&gt;XStream.asyncRead&lt;/em&gt; is used instead of &lt;em&gt;XStream.read&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Well I think I have provided enough information and examples to enable you to go play with the XAM query language by yourself.  It you need help the I am sure the &lt;a href="http://groups.google.com/group/xam-developers-group"&gt;XAM Developer Group&lt;/a&gt; on Google Groups will be more than happy to help you.&lt;br /&gt;&lt;br /&gt;In parting I would point out that since XAM Storage System providers are currently only required to implement support for queries over the content metadata, I suspect that support for actual full content-based searches using XAM may not occur for some time.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-6060261547235990067?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/6060261547235990067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/07/xam-query-language.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/6060261547235990067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/6060261547235990067'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/07/xam-query-language.html' title='XAM Query Language'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-9199546494070469115</id><published>2009-07-06T00:02:00.000-04:00</published><updated>2009-08-22T00:03:01.956-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='HPET'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Linux HPET Support</title><content type='html'>&lt;a href='http://www.intel.com/hardwaredesign/hpetspec_1.pdf'&gt;IA-PC HPET&lt;/a&gt; (High Precision Event Timer) is a specification which was jointly developed by Intel and Microsoft in the early part of this decade.. The latest version is dated October 2004.  It's stated purpose is to &lt;blockquote&gt;initially supplement and eventually replace the legacy 8254 Programmable Interval Timer and the Real Time Clock Periodic Interrupt generation functions that are currently used as the ‘de-facto’ timer hardware for IA-PCs.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href='http://en.wikipedia.org/wiki/High_Precision_Event_Timer'&gt; HPET&lt;/a&gt; architecture defines a set of timers that can be used by the operating system.  A timer block is a combination of a single counter and up to 32 comparators and match registers. The comparator compares the contents of  the match register against the value of a free running monotonic up-counter.  When the output of the up-counter equals the value in the match register an interrupt is generated. Each of the comparators can output an interrupt.  A maximum of  8 timer blocks are supported for a total of 256 timers.  Each timer block can have different clocking attributes. Specific implementations may include only a subset of these timers.  A minimum of three timers is required.  &lt;br /&gt;&lt;br /&gt;The specification contains the following block diagram of the HPET architecture.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://blog.fpmurphy.com/blog-images/hpet-1.png" alt="Hardware Block Diagram" /&gt;&lt;br /&gt;&lt;br /&gt;Some of the timers may be enabled to generate a periodic interrupt.  If a timer is set to be periodic, its period is added to the match register each time a match occurs, thus computing the next time for this timer to generate an interrupt..  An up-counter is usually 64 bits wide but 32-bit implementations are permitted by the specification and 64-bit up-counters can also be driven in 32-bit mode.  Up-counters run at a minimum of 10 MHz. which is much faster than the older &lt;a href='http://en.wikipedia.org/wiki/Real-time_clock'&gt;RTC&lt;/a&gt; (Real Time Clock) and can thus produce periodic interrupts at a much higher resolution. The registers associated with these timers are mapped to memory space. &lt;br /&gt;&lt;br /&gt;The BIOS uses &lt;a href='http://www.acpica.org/'&gt;ACPI&lt;/a&gt;  ( Advanced Configuration and Power Interface) functionality to inform the operating system of the location of the HPET memory-mapped register space.  Here is an example of a disassembled ACPI HPET table from an Intel DX48BT2 (AKA BoneTrail) motherboard.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ cat /sys/firmware/acpi/tables/HPET &gt; /var/tmp/hpet.out&lt;br /&gt;$ iasl -d /var/tmp/hpet.out&lt;br /&gt;$ cat /var/tmp/hpet.dsl&lt;br /&gt;/*&lt;br /&gt; * Intel ACPI Component Architecture&lt;br /&gt; * AML Disassembler version 20090123&lt;br /&gt; *&lt;br /&gt; * Disassembly of /var/tmp/hpet.out, Sun Jul  5 19:34:47 2009&lt;br /&gt; *&lt;br /&gt; * ACPI Data Table [HPET]&lt;br /&gt; *&lt;br /&gt; * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;[000h 000  4]                    Signature : "HPET"    /* High Precision Event Timer table */&lt;br /&gt;[004h 004  4]                 Table Length : 00000038&lt;br /&gt;[008h 008  1]                     Revision : 01&lt;br /&gt;[009h 009  1]                     Checksum : CE&lt;br /&gt;[00Ah 010  6]                       Oem ID : "INTEL "&lt;br /&gt;[010h 016  8]                 Oem Table ID : "DX48BT2 "&lt;br /&gt;[018h 024  4]                 Oem Revision : 0000076E&lt;br /&gt;[01Ch 028  4]              Asl Compiler ID : "MSFT"&lt;br /&gt;[020h 032  4]        Asl Compiler Revision : 01000013&lt;br /&gt;&lt;br /&gt;[024h 036  4]            Hardware Block ID : 8086A301&lt;br /&gt;&lt;br /&gt;[028h 040 12]         Timer Block Register : &lt;Generic Address Structure&gt;&lt;br /&gt;[028h 040  1]                     Space ID : 00 (SystemMemory)&lt;br /&gt;[029h 041  1]                    Bit Width : 00&lt;br /&gt;[02Ah 042  1]                   Bit Offset : 00&lt;br /&gt;[02Bh 043  1]                 Access Width : 00&lt;br /&gt;[02Ch 044  8]                      Address : 00000000FED00000&lt;br /&gt;&lt;br /&gt;[034h 052  1]              Sequence Number : 00&lt;br /&gt;[035h 053  2]          Minimum Clock Ticks : 0001&lt;br /&gt;[037h 055  1]        Flags (decoded below) : 00&lt;br /&gt;                              Page Protect : 0&lt;br /&gt;                           4K Page Protect : 0&lt;br /&gt;                          64K Page Protect : 0&lt;br /&gt;Raw Table Data&lt;br /&gt;&lt;br /&gt;  0000: 48 50 45 54 38 00 00 00 01 CE 49 4E 54 45 4C 20  HPET8.....INTEL&lt;br /&gt;  0010: 44 58 34 38 42 54 32 20 6E 07 00 00 4D 53 46 54  DX48BT2 n...MSFT&lt;br /&gt;  0020: 13 00 00 01 01 A3 86 80 00 00 00 00 00 00 D0 FE  ................&lt;br /&gt;  0030: 00 00 00 00 00 01 00 00                          ........&lt;br /&gt;$&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;See page 30 of the HPET v1.0a specification for a detailed breakdown of the individual bits in the Event Time Block (called Hardware Block by the AML disassember).  Note that only one Event Timer Block need be described in the HPET table in order to bootstrap an operating system. This is the case here. For non-legacy platforms, the Event Timer Block described in the HPET is the one that provides functionality to replace the 8254/RTC Periodic Interrupt Logic.  &lt;br /&gt;&lt;br /&gt;Other Event Time Blocks are described in the ACPI namespace.  Here is the relevant section from the disassembled ACPI DSDT table. &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;            Device (HPET)&lt;br /&gt;            {&lt;br /&gt;                Name (_HID, EisaId ("PNP0103"))&lt;br /&gt;                Name (_CRS, ResourceTemplate ()&lt;br /&gt;                {&lt;br /&gt;                    Memory32Fixed (ReadOnly,&lt;br /&gt;                        0xFED00000,         // Address Base&lt;br /&gt;                        0x00004000,         // Address Length&lt;br /&gt;                        )&lt;br /&gt;                })&lt;br /&gt;                Method (_STA, 0, NotSerialized)&lt;br /&gt;                {&lt;br /&gt;                    If (HPEE)&lt;br /&gt;                    {&lt;br /&gt;                        Return (0x0F)&lt;br /&gt;                    }&lt;br /&gt;                    Else&lt;br /&gt;                    {&lt;br /&gt;                        Return (Zero)&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Note the assigned PNPID (&lt;em&gt;PNP0103&lt;/em&gt;) for the HPET.  Because no _UID is specified it means that there are no other HPET timer blocks.&lt;br /&gt;&lt;br /&gt;Here is a list of the HPET-related messages outputted when this particular motherboard is booted up under Fedora 11.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ dmesg | grep -i HPET&lt;br /&gt;ACPI: HPET CFBF2000, 0038 (r1 INTEL  DX48BT2       76E MSFT  1000013)&lt;br /&gt;ACPI: HPET id: 0x8086a301 base: 0xfed00000&lt;br /&gt;hpet clockevent registered&lt;br /&gt;HPET: 4 timers in total, 0 timers will be used for per-cpu timer&lt;br /&gt;hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, 0&lt;br /&gt;hpet0: 4 comparators, 64-bit 14.318180 MHz counter&lt;br /&gt;rtc0: alarms up to one month, 114 bytes nvram, hpet irqs&lt;br /&gt;$ &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The first line is outputted when the ACPI HPET table is read.  The second line is outputted when the ACPI HPET table is mapped into memory by  &lt;em&gt;.../arch/x86/kernel/acpi/boot.c&lt;/em&gt;.  The next line is outputted when the HPET legacy interrupts are started and HPET is registered as the global clock.  The following line is outputted when  the kernel checks to ensure that at least one timer is reserved for userspace (&lt;em&gt;/dev/hpet&lt;/em&gt;.)  The next two lines of output comes from the HPET device driver (&lt;em&gt;.../drivers/char/hpet.c&lt;/em&gt;.)  It shows that 2 timers have allocated interrupts and two do not..  &lt;br /&gt;&lt;br /&gt;Here is the relevant part of the output from &lt;em&gt;/proc/time_list&lt;/em&gt; as it relates to HPET:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;Tick Device: mode:     1&lt;br /&gt;Broadcast device&lt;br /&gt;Clock Event Device: hpet&lt;br /&gt; max_delta_ns:   149983005959&lt;br /&gt; min_delta_ns:   5000&lt;br /&gt; mult:           61496114&lt;br /&gt; shift:          32&lt;br /&gt; mode:           3&lt;br /&gt; next_event:     9223372036854775807 nsecs&lt;br /&gt; set_next_event: hpet_legacy_next_event&lt;br /&gt; set_mode:       hpet_legacy_set_mode&lt;br /&gt; event_handler:  tick_handle_oneshot_broadcast&lt;br /&gt;tick_broadcast_mask: 00000000&lt;br /&gt;tick_broadcast_oneshot_mask: 00000000&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output from  &lt;em&gt;/proc/sys/dev/hpet&lt;/em&gt; and &lt;em&gt;/proc/driver/rtc&lt;/em&gt;:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ cat /proc/sys/dev/hpet/max-user-freq&lt;br /&gt;64&lt;br /&gt;$ cat /proc/driver/rtc&lt;br /&gt;rtc_time : 06:34:31&lt;br /&gt;rtc_date : 2009-07-06&lt;br /&gt;alrm_time : **:24:40&lt;br /&gt;alrm_date : ****-**-**&lt;br /&gt;alarm_IRQ : no&lt;br /&gt;alrm_pending : no&lt;br /&gt;24hr  : yes&lt;br /&gt;periodic_IRQ : no&lt;br /&gt;update_IRQ : no&lt;br /&gt;HPET_emulated : yes&lt;br /&gt;DST_enable : no&lt;br /&gt;periodic_freq : 1024&lt;br /&gt;batt_status : okay&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;&lt;br /&gt;The HPET driver (&lt;em&gt;/dev/hpet&lt;/em&gt;)  has a similar API to the Real Time Clock driver.  It is a character device which can support any number of HPET devices.  The kernel API has three interfaces exported from the driver: &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;hpet_register( struct hpet_task *tp, int periodic )&lt;br /&gt;hpet_unregister( struct hpet_task *tp )&lt;br /&gt;hpet_control( struct hpet_task *tp, unsigned int cmd, unsigned long arg )&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The userspace interface to HPET is defined in the header &lt;em&gt;/usr/include/linux/hpet.h&lt;/em&gt;.  The current set of supported operations is:&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;#define HPET_IE_ON      _IO('h', 0x01)                        /* interrupt on */&lt;br /&gt;#define HPET_IE_OFF     _IO('h', 0x02)                        /* interrupt off */&lt;br /&gt;#define HPET_INFO       _IOR('h', 0x03, struct hpet_info)     /* get information */&lt;br /&gt;#define HPET_EPI        _IO('h', 0x04)                        /* enable periodic */&lt;br /&gt;#define HPET_DPI        _IO('h', 0x05)                        /* disable periodic */&lt;br /&gt;#define HPET_IRQFREQ    _IOW('h', 0x6, unsigned long)         /* set frequency */&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;The following example shows how to use the published interface to access a &lt;span class='notranslate'&gt;HPET&lt;/span&gt; and call a simple periodic signal handler &lt;span class='notranslate'&gt;&lt;em&gt;hpet_alarm&lt;/em&gt;&lt;/span&gt; between 2 and 99 times a second. &lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h;&amp;gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;#include &amp;lt;time.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;#include &amp;lt;linux/hpet.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;&lt;br /&gt;static uint16_t hpet_sigio_count;&lt;br /&gt;static uint64_t secs;&lt;br /&gt;&lt;br /&gt;static void&lt;br /&gt;hpet_alarm(int val)&lt;br /&gt;{&lt;br /&gt;   struct timespec t;&lt;br /&gt;   clock_gettime(CLOCK_REALTIME, &amp;t);&lt;br /&gt;&lt;br /&gt;   if (!secs)  secs = t.tv_sec;&lt;br /&gt;&lt;br /&gt;   fprintf(stderr, "hpet_alarm called. iteration: %2d  secs: %ld  nsecs: %ld \n",&lt;br /&gt;                    hpet_sigio_count, (t.tv_sec - secs) , t.tv_sec * 100000 + t.tv_nsec );&lt;br /&gt;&lt;br /&gt;   hpet_sigio_count++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main(int argc, const char **argv)&lt;br /&gt;{&lt;br /&gt;    struct sigaction old, new;&lt;br /&gt;    struct hpet_info info;&lt;br /&gt;    int              frequency;&lt;br /&gt;    int              iterations;&lt;br /&gt;    int              retval = 0;&lt;br /&gt;    int              fd;&lt;br /&gt;    int              r, i, value;&lt;br /&gt;&lt;br /&gt;    if (argc != 3) {&lt;br /&gt;        fprintf(stderr, "Usage: %s frequency(1-64) iterations(10-99)\n", argv[0]);&lt;br /&gt;        return -1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    frequency = atoi(argv[1]);&lt;br /&gt;    iterations = atoi(argv[2]);&lt;br /&gt;&lt;br /&gt;    if (frequency &gt; 64 || frequency &lt; 1 ) {&lt;br /&gt;        fprintf(stderr, "ERROR: Invalid value for frequency\n");&lt;br /&gt;        return -1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (iterations &lt; 10 || iterations &gt; 99 ) {&lt;br /&gt;        fprintf(stderr, "ERROR: Invalid value for iterations\n");&lt;br /&gt;        return -1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    hpet_sigio_count = 0;&lt;br /&gt;&lt;br /&gt;    sigemptyset(&amp;new.sa_mask);&lt;br /&gt;    new.sa_flags = 0;&lt;br /&gt;    new.sa_handler = hpet_alarm;&lt;br /&gt;&lt;br /&gt;    sigaction(SIGIO, NULL, &amp;old);&lt;br /&gt;    sigaction(SIGIO, &amp;new, NULL);&lt;br /&gt;&lt;br /&gt;    fd = open("/dev/hpet", O_RDONLY);&lt;br /&gt;    if (fd &lt; 0) {&lt;br /&gt;        fprintf(stderr, "ERROR: Failed to open /dev/hpet\n");&lt;br /&gt;        return -1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||&lt;br /&gt;        ((value = fcntl(fd, F_GETFL)) == 1) ||&lt;br /&gt;        (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {&lt;br /&gt;        fprintf(stderr, "ERROR: fcntl failed\n");&lt;br /&gt;        retval = 1;&lt;br /&gt;        goto fail;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (ioctl(fd, HPET_IRQFREQ, frequency) &lt; 0) {&lt;br /&gt;        fprintf(stderr, "ERROR: Could not set /dev/hpet to have a %2dHz timer\n", frequency);&lt;br /&gt;        retval = 2;&lt;br /&gt;        goto fail;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (ioctl(fd, HPET_INFO, &amp;info) &lt; 0) {&lt;br /&gt;        fprintf(stderr, "ERROR: failed to get info\n");&lt;br /&gt;        retval = 3;&lt;br /&gt;        goto fail;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fprintf(stdout, "\nhi_ireqfreq: 0x%lx  hi_flags: %0x%lx  hi_hpet: 0x%x  hi_timer: 0x%x\n\n",&lt;br /&gt;            info.hi_ireqfreq,  info.hi_flags, info.hi_hpet, info.hi_timer);&lt;br /&gt;&lt;br /&gt;    r = ioctl(fd, HPET_EPI, 0);&lt;br /&gt;    if (info.hi_flags &amp;&amp; (r &lt; 0)) {&lt;br /&gt;        fprintf(stderr, "ERROR:  HPET_EPI failed\n");&lt;br /&gt;        retval = 4;&lt;br /&gt;        goto fail;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (ioctl(fd, HPET_IE_ON, 0) &lt; 0) {&lt;br /&gt;        fprintf(stderr, "ERROR: HPET_IE_ON failed\n");&lt;br /&gt;        retval = 5;&lt;br /&gt;        goto fail;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /* wait for specified number of signal interrupts */&lt;br /&gt;    for (i = 0; i &lt; iterations; i++) {&lt;br /&gt;        (void) pause();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (ioctl(fd, HPET_IE_OFF, 0) &lt; 0) {&lt;br /&gt;        fprintf(stderr, "ERROR: HPET_IE_OFF failed\n");&lt;br /&gt;        retval = 6;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;fail:&lt;br /&gt;    sigaction(SIGIO, &amp;old, NULL);&lt;br /&gt;&lt;br /&gt;    if (fd &gt; 0)&lt;br /&gt;        close(fd);&lt;br /&gt;&lt;br /&gt;    return retval;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Here is the output from this example when it is invoked with a frequency of 32 and an iteration count of 64.&lt;br /&gt;&lt;!--skip translation--&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;&lt;br /&gt;$ sudo ./hpet_example 32 64&lt;br /&gt;&lt;br /&gt;hi_ireqfreq: 0x20  hi_flags: 00  hi_hpet: 0x2  hi_timer: 0x4a1cb9c8&lt;br /&gt;&lt;br /&gt;hpet_alarm called. iteration:  0  secs: 0  nsecs: 124683205055050 &lt;br /&gt;hpet_alarm called. iteration:  1  secs: 0  nsecs: 124683236313149 &lt;br /&gt;hpet_alarm called. iteration:  2  secs: 0  nsecs: 124683267566342 &lt;br /&gt;hpet_alarm called. iteration:  3  secs: 0  nsecs: 124683298821905 &lt;br /&gt;hpet_alarm called. iteration:  4  secs: 0  nsecs: 124683330077493 &lt;br /&gt;hpet_alarm called. iteration:  5  secs: 0  nsecs: 124683361341893 &lt;br /&gt;hpet_alarm called. iteration:  6  secs: 0  nsecs: 124683392590764 &lt;br /&gt;hpet_alarm called. iteration:  7  secs: 0  nsecs: 124683423849157 &lt;br /&gt;hpet_alarm called. iteration:  8  secs: 0  nsecs: 124683455101917 &lt;br /&gt;hpet_alarm called. iteration:  9  secs: 0  nsecs: 124683486357683 &lt;br /&gt;hpet_alarm called. iteration: 10  secs: 0  nsecs: 124683517617931 &lt;br /&gt;hpet_alarm called. iteration: 11  secs: 0  nsecs: 124683548872198 &lt;br /&gt;hpet_alarm called. iteration: 12  secs: 1  nsecs: 124682580229541 &lt;br /&gt;hpet_alarm called. iteration: 13  secs: 1  nsecs: 124682611481235 &lt;br /&gt;hpet_alarm called. iteration: 14  secs: 1  nsecs: 124682642740016 &lt;br /&gt;hpet_alarm called. iteration: 15  secs: 1  nsecs: 124682673992697 &lt;br /&gt;hpet_alarm called. iteration: 16  secs: 1  nsecs: 124682705247479 &lt;br /&gt;hpet_alarm called. iteration: 17  secs: 1  nsecs: 124682736504664 &lt;br /&gt;hpet_alarm called. iteration: 18  secs: 1  nsecs: 124682767758840 &lt;br /&gt;hpet_alarm called. iteration: 19  secs: 1  nsecs: 124682799014280 &lt;br /&gt;hpet_alarm called. iteration: 20  secs: 1  nsecs: 124682830270129 &lt;br /&gt;hpet_alarm called. iteration: 21  secs: 1  nsecs: 124682861530334 &lt;br /&gt;hpet_alarm called. iteration: 22  secs: 1  nsecs: 124682892784577 &lt;br /&gt;hpet_alarm called. iteration: 23  secs: 1  nsecs: 124682924038220 &lt;br /&gt;hpet_alarm called. iteration: 24  secs: 1  nsecs: 124682955294110 &lt;br /&gt;hpet_alarm called. iteration: 25  secs: 1  nsecs: 124682986550572 &lt;br /&gt;hpet_alarm called. iteration: 26  secs: 1  nsecs: 124683017805756 &lt;br /&gt;hpet_alarm called. iteration: 27  secs: 1  nsecs: 124683049061117 &lt;br /&gt;hpet_alarm called. iteration: 28  secs: 1  nsecs: 124683080318331 &lt;br /&gt;hpet_alarm called. iteration: 29  secs: 1  nsecs: 124683111576954 &lt;br /&gt;hpet_alarm called. iteration: 30  secs: 1  nsecs: 124683142828988 &lt;br /&gt;hpet_alarm called. iteration: 31  secs: 1  nsecs: 124683174083954 &lt;br /&gt;hpet_alarm called. iteration: 32  secs: 1  nsecs: 124683205337967 &lt;br /&gt;hpet_alarm called. iteration: 33  secs: 1  nsecs: 124683236593144 &lt;br /&gt;hpet_alarm called. iteration: 34  secs: 1  nsecs: 124683267851530 &lt;br /&gt;hpet_alarm called. iteration: 35  secs: 1  nsecs: 124683299104054 &lt;br /&gt;hpet_alarm called. iteration: 36  secs: 1  nsecs: 124683330358748 &lt;br /&gt;hpet_alarm called. iteration: 37  secs: 1  nsecs: 124683361617445 &lt;br /&gt;hpet_alarm called. iteration: 38  secs: 1  nsecs: 124683392870249 &lt;br /&gt;hpet_alarm called. iteration: 39  secs: 1  nsecs: 124683424124489 &lt;br /&gt;hpet_alarm called. iteration: 40  secs: 1  nsecs: 124683455379717 &lt;br /&gt;hpet_alarm called. iteration: 41  secs: 1  nsecs: 124683486634424 &lt;br /&gt;hpet_alarm called. iteration: 42  secs: 1  nsecs: 124683517889149 &lt;br /&gt;hpet_alarm called. iteration: 43  secs: 1  nsecs: 124683549144315 &lt;br /&gt;hpet_alarm called. iteration: 44  secs: 2  nsecs: 124682580500695 &lt;br /&gt;hpet_alarm called. iteration: 45  secs: 2  nsecs: 124682611761325 &lt;br /&gt;hpet_alarm called. iteration: 46  secs: 2  nsecs: 124682643011863 &lt;br /&gt;hpet_alarm called. iteration: 47  secs: 2  nsecs: 124682674265864 &lt;br /&gt;hpet_alarm called. iteration: 48  secs: 2  nsecs: 124682705521034 &lt;br /&gt;hpet_alarm called. iteration: 49  secs: 2  nsecs: 124682736776049 &lt;br /&gt;hpet_alarm called. iteration: 50  secs: 2  nsecs: 124682768030654 &lt;br /&gt;hpet_alarm called. iteration: 51  secs: 2  nsecs: 124682799285398 &lt;br /&gt;hpet_alarm called. iteration: 52  secs: 2  nsecs: 124682830544701 &lt;br /&gt;hpet_alarm called. iteration: 53  secs: 2  nsecs: 124682861797319 &lt;br /&gt;hpet_alarm called. iteration: 54  secs: 2  nsecs: 124682893051578 &lt;br /&gt;hpet_alarm called. iteration: 55  secs: 2  nsecs: 124682924306748 &lt;br /&gt;hpet_alarm called. iteration: 56  secs: 2  nsecs: 124682955562132 &lt;br /&gt;hpet_alarm called. iteration: 57  secs: 2  nsecs: 124682986823545 &lt;br /&gt;hpet_alarm called. iteration: 58  secs: 2  nsecs: 124683018073636 &lt;br /&gt;hpet_alarm called. iteration: 59  secs: 2  nsecs: 124683049327560 &lt;br /&gt;hpet_alarm called. iteration: 60  secs: 2  nsecs: 124683080586707 &lt;br /&gt;hpet_alarm called. iteration: 61  secs: 2  nsecs: 124683111841132 &lt;br /&gt;hpet_alarm called. iteration: 62  secs: 2  nsecs: 124683143095147 &lt;br /&gt;hpet_alarm called. iteration: 63  secs: 2  nsecs: 124683174349985 &lt;br /&gt;hpet_alarm called. iteration: 64  secs: 2  nsecs: 124683205607103 &lt;br /&gt;$ &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--end skip translation--&gt;&lt;br /&gt;Well, I think that I have provided you with enough information so that you should now be able to go away and experiment with the HPET interface yourself.&lt;br /&gt;&lt;br /&gt;By the way, not all VMware products support HPET.  Currently ESX does not provide a virtual HPET to guest operating systems and in some cases it may be necessary to disable HPET altogether because of timer drift in virtual machines. See &lt;a href='http://www.vmware.com/pdf/vmware_timekeeping.pdf'&gt;VMware TimeKeeping&lt;/a&gt; for more information. &lt;br /&gt;&lt;br /&gt;P.S. I tested the the above example on an Intel DX48BT2 motherboard running a 2.6.29.5-191 kernel.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-9199546494070469115?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/9199546494070469115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/07/linux-hpet-support.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/9199546494070469115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/9199546494070469115'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/07/linux-hpet-support.html' title='Linux HPET Support'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-1587264670659520885</id><published>2009-06-29T13:34:00.000-04:00</published><updated>2009-08-23T13:35:32.213-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SNIA'/><category scheme='http://www.blogger.com/atom/ns#' term='XAM'/><title type='text'>XAM Mandated Fields</title><content type='html'>In this post I look at what fields are mandated by the SNIA XAM v1.0 specification and write a small Java application to retrieve their default values using the XAM Reference VIM and EMC's Centera XAM VIM.&lt;br /&gt;&lt;br /&gt;What is meant by a field in XAM?  According to Section 3.1.5 of the XAM specification v1.0, Part 1, a field is &lt;blockquote&gt; a piece of uniquely identifiable data that can be attached to an XSet, an XSystem, or a XAM Library.&lt;/blockquote&gt;  More concretely, a field has a name, a number of attributes that describe how to interact with the object, and a value.  Any XAM primary object, i.e. an XSystem, an XSet, or a XAM Library object can contain one or more fields. &lt;br /&gt;&lt;br /&gt;Field names are case sentitive UTF-8 encoded strings with a maximum length of 512 bytes and no embedded NULL characters.  To avoid namespace clashes, the field namespace is allocated between SNIA, XAM storage system vendors and XAM application vendors. The following table shows the currently reserved namespace for field names:&lt;br /&gt;[table id=7 /]&lt;br /&gt;To avoid field namespace clashes between XAM storage system vendors in the remaining unreserved namespace and aleviate the need for a central XAM field name registry, the first portion of a vendor field name shall be the vendor's domain name in reverse order, followed by the vendor-defined field name, e.g. &lt;em&gt;com.emc.centera.xam.vim.version&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;As mentionly previously a field can have attributes. The following four attributes are mandated by the XAM specification:&lt;br /&gt;[table id=8 /]&lt;br /&gt;Two distinct types of fields exist: a property and an XStream. For the purposes of this post, we are only interested in fields which are properties as defined in section 3.1.12 of the XAM specification, i.e&lt;blockquote&gt; a field whose MIME type attribute is one of the XAM-defined simple types (stypes).&lt;/blockquote&gt;&lt;br /&gt;Here is a list of the specified XAM stypes:&lt;br /&gt;[table id=9 /]&lt;br /&gt;Turning now to the two objects that we are interested in, namely the XAM Library object and the XSystem object.  &lt;br /&gt;&lt;br /&gt;XAM Library properties are always nonbinding i.e. a change in the property value does not trigger the creation of a new XSet with a corresponding new XUID. Some may be readonly and intended to be only inspected by the application. Others such as &lt;em&gt;.xam.log.level&lt;/em&gt; may be modifiable by a XAM application to effect a change in the behavior of the XAM Library object.  Note however that changes are not persisted by the XAM Library. &lt;br /&gt;&lt;br /&gt;Here is the list of the mandated properties for the XAM Library:&lt;br /&gt;[table id=1 /]&lt;br /&gt;An XSystem property is strongly typed to help XAM application interoperability. The stype is checked and the actual MIME type is set based on the specific method that the XAM application uses to create the field.  A number of other field consistency checks are also done by an XSystem including checking that field names do not begin with a period, are a valid &lt;em&gt;xam_string&lt;/em&gt; and do not have embedded NULLs.  See section 6.3.5 of the XAM specification for a complete description of the field consistency checks. &lt;br /&gt;&lt;br /&gt;Here is the list of mandated properties for an XSystem object:&lt;br /&gt;[table id=2 /]&lt;br /&gt;Here is a simple Java application which iterates over the list of available fields and output the fields which match the specified field prefix or all fields if no prefix is entered. It uses the XAM &lt;em&gt;FieldIterator&lt;/em&gt; class to retrieve the requested fields from either the SNIA-XAM SDK reference VIM  or a third party VIM such as the EMC Centera VIM. &lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;import java.io.ByteArrayOutputStream;&lt;br /&gt;import java.io.BufferedOutputStream;&lt;br /&gt;import java.io.BufferedInputStream;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;&lt;br /&gt;import java.util.Calendar;&lt;br /&gt;import java.text.SimpleDateFormat;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;&lt;br /&gt;import org.snia.xam.XAMLibrary;&lt;br /&gt;import org.snia.xam.XAMLibraryObj;&lt;br /&gt;import org.snia.xam.XAMException;&lt;br /&gt;import org.snia.xam.XSystem;&lt;br /&gt;import org.snia.xam.XSet;&lt;br /&gt;import org.snia.xam.XIterator;&lt;br /&gt;import org.snia.xam.toolkit.XAMXUID;&lt;br /&gt;import org.snia.xam.util.XAMLibraryFactory;&lt;br /&gt;import org.snia.xam.FieldContainer;&lt;br /&gt;&lt;br /&gt;import org.snia.xam.XUID;&lt;br /&gt;import org.snia.xam.base.XAMImplementation;&lt;br /&gt;import org.snia.xam.util.SASLUtils;&lt;br /&gt;import org.snia.xam.vim.reference.ReferenceAuthenticationStatus;&lt;br /&gt;import org.snia.xam.vim.reference.utils.ReferenceSaslUtils;&lt;br /&gt;&lt;br /&gt;public class XamFieldIterator {&lt;br /&gt;    private static XAMLibrary xamLib;&lt;br /&gt;    private static XSystem xSystem;&lt;br /&gt;    protected static String xri;&lt;br /&gt;&lt;br /&gt;    public static boolean  IS_REFERENCE_VIM = false;&lt;br /&gt;    public static final String TEST_PROP_FILE = "xam.test.props";&lt;br /&gt;    public static final String XRI_PROP  = "xam.test.xri";&lt;br /&gt;    public static final String CONFIG_PROP = "xam.test.vims";&lt;br /&gt;    public static final String USER_PROP = "xam.test.username";&lt;br /&gt;    public static final String PASS_PROP = "xam.test.password";&lt;br /&gt;    protected static final String DEFAULT_USER = "test";&lt;br /&gt;    protected static final String DEFAULT_PASS = "test";&lt;br /&gt;    protected static String s_pass;&lt;br /&gt;    protected static String s_user;&lt;br /&gt;&lt;br /&gt;    public static void initLibrary() throws Exception {&lt;br /&gt;        if (xamLib == null) {&lt;br /&gt;            System.out.println("\nInitializing VIM");&lt;br /&gt;            Properties props = new Properties();&lt;br /&gt;            String testPropFile = System.getProperty(TEST_PROP_FILE);&lt;br /&gt;            if (testPropFile == null)&lt;br /&gt;                testPropFile = TEST_PROP_FILE;&lt;br /&gt;&lt;br /&gt;            System.out.println("Loading test properties from file: " + testPropFile);&lt;br /&gt;            props.load(new FileInputStream(testPropFile));&lt;br /&gt;&lt;br /&gt;            xri = props.getProperty(XRI_PROP);&lt;br /&gt;            s_user = props.getProperty(USER_PROP, DEFAULT_USER);&lt;br /&gt;            s_pass = props.getProperty(PASS_PROP, DEFAULT_PASS);&lt;br /&gt;&lt;br /&gt;            // XAM Library loads the VIM name and associated Java implementation class&lt;br /&gt;            System.out.println("Loading the VIM using the Java XAM Library.");&lt;br /&gt;            System.out.println("VIM Configuration contained in file: " +&lt;br /&gt;                    props.getProperty(CONFIG_PROP));&lt;br /&gt;            xamLib = new XAMImplementation(props.getProperty(CONFIG_PROP));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static XSystem connectToVIM(String xri) throws Exception {&lt;br /&gt;        XSystem xsystem = null;&lt;br /&gt;        xsystem = xamLib.connect(xri);&lt;br /&gt;        return xsystem;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static void authenticate(XSystem system) throws XAMException {&lt;br /&gt;        String defMech = system.getString(XSystem.XAM_XSYSTEM_AUTH_SASL_DEFAULT);&lt;br /&gt;        ByteArrayOutputStream response = new ByteArrayOutputStream(200);&lt;br /&gt;        byte[] inputData = null;&lt;br /&gt;        int retValue = 0;&lt;br /&gt;&lt;br /&gt;        if (defMech.equals(ReferenceSaslUtils.SASL_MECHANISM_ANONYMOUS)) {&lt;br /&gt;            retValue = system.authenticate(inputData, response);&lt;br /&gt;        } else if (defMech.equals(SASLUtils.SASL_PLAIN)) {&lt;br /&gt;            byte[] creds = ReferenceSaslUtils.encodeSASLPlain(null,&lt;br /&gt;                    ReferenceAuthenticationStatus.TEST_USERNAME,&lt;br /&gt;                    ReferenceAuthenticationStatus.TEST_PASSWORD);&lt;br /&gt;            retValue = system.authenticate(creds, response);&lt;br /&gt;        } else {&lt;br /&gt;            throw new XAMException("Unknown default SASL mechanism " + defMech);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Validate return status value&lt;br /&gt;        if (retValue != XSystem.XAM_SASL_COMPLETE) {&lt;br /&gt;            throw new XAMException("Failed to authenticate.");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /* a FieldContainer is a XAM superclass for the 3 primary objects (XAMLibrary, XSystem, XSet) */&lt;br /&gt;    private static void iterateFields(FieldContainer fieldContainer, String prefix) throws XAMException {&lt;br /&gt;        String fieldName;&lt;br /&gt;        String fieldType;&lt;br /&gt;        String fieldValue;&lt;br /&gt;        String fieldBinding;&lt;br /&gt;        String fieldReadOnly;&lt;br /&gt;&lt;br /&gt;        XIterator xIterator = fieldContainer.openFieldIterator(prefix);&lt;br /&gt;        while (xIterator.hasNext()) {&lt;br /&gt;            fieldName = (String)xIterator.next();&lt;br /&gt;            fieldType = fieldContainer.getFieldType(fieldName);&lt;br /&gt;&lt;br /&gt;            fieldBinding = fieldContainer.getFieldBinding(fieldName) != true ? "NB" : "BI";&lt;br /&gt;            fieldReadOnly =  fieldContainer.getFieldReadOnly(fieldName) != true ? "RW" : "RO";&lt;br /&gt;&lt;br /&gt;            if (fieldType.equals(XAMLibrary.STYPE_BOOLEAN_MIME_TYPE))&lt;br /&gt;                fieldValue = fieldContainer.getBoolean(fieldName) != true ? "false" : "true";&lt;br /&gt;            else if (fieldType.equals(XAMLibrary.STYPE_INT_MIME_TYPE))&lt;br /&gt;                fieldValue = Long.toString(fieldContainer.getLong(fieldName));&lt;br /&gt;            else if (fieldType.equals(XAMLibrary.STYPE_DOUBLE_MIME_TYPE))&lt;br /&gt;                fieldValue = Double.toString(fieldContainer.getDouble(fieldName));&lt;br /&gt;            else if (fieldType.equals(XAMLibrary.STYPE_XUID_MIME_TYPE))&lt;br /&gt;                fieldValue = fieldContainer.getXUID(fieldName).toString();&lt;br /&gt;            else if (fieldType.equals(XAMLibrary.STYPE_STRING_MIME_TYPE))&lt;br /&gt;                fieldValue = fieldContainer.getString(fieldName);&lt;br /&gt;            else if (fieldType.equals(XAMLibrary.STYPE_DATETIME_MIME_TYPE)) {&lt;br /&gt;                Calendar now = fieldContainer.getDateTime(fieldName);&lt;br /&gt;                int Y = now.get(Calendar.YEAR);&lt;br /&gt;                int M = now.get(Calendar.MONTH);&lt;br /&gt;                int D = now.get(Calendar.DAY_OF_MONTH);&lt;br /&gt;                int h = now.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;                int m = now.get(Calendar.MINUTE);&lt;br /&gt;                int s = now.get(Calendar.SECOND);&lt;br /&gt;                fieldValue = Y + "-" + M + "-" + D + " " + h + ":" + m + ":" + s;&lt;br /&gt;            } else&lt;br /&gt;                fieldValue = fieldContainer.getFieldLength(fieldName) + " bytes";&lt;br /&gt;&lt;br /&gt;            System.out.println(String.format("%s   (%s) %s %s   \"%s\"",&lt;br /&gt;                 fieldName, fieldType, fieldBinding, fieldReadOnly, fieldValue));&lt;br /&gt;        }&lt;br /&gt;        xIterator.close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        long exitCode = 0;&lt;br /&gt;&lt;br /&gt;        InputStreamReader inputReader = new InputStreamReader(System.in);&lt;br /&gt;        BufferedReader stdin = new BufferedReader(inputReader);&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            /* simple check for command line option of "-r" */&lt;br /&gt;            if (args.length == 1 ) {&lt;br /&gt;               if (args[0].equals("-r"))&lt;br /&gt;                  IS_REFERENCE_VIM = true;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            if (IS_REFERENCE_VIM) {&lt;br /&gt;                initLibrary();&lt;br /&gt;                System.out.println("Connecting to XSystem " + xri + "\n");&lt;br /&gt;                xSystem = connectToVIM(xri);&lt;br /&gt;                authenticate(xSystem);&lt;br /&gt;            } else {&lt;br /&gt;                xri = "snia-xam://centera_vim!128.221.200.60?/home/fpm/xam/xamconnect.pea";&lt;br /&gt;                xamLib = XAMLibraryFactory.newXAMLibrary();&lt;br /&gt;                System.out.println("Connecting to XSystem " + xri + "\n");&lt;br /&gt;                xSystem = xamLib.connect(xri);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            System.out.print("Enter prefix to filter results (blank for all): ");&lt;br /&gt;            String prefix = stdin.readLine();&lt;br /&gt;&lt;br /&gt;            iterateFields(xSystem, prefix);&lt;br /&gt;&lt;br /&gt;            xSystem.close();&lt;br /&gt;            System.out.println( "\nClosed connection to XSystem" );&lt;br /&gt;&lt;br /&gt;        } catch (XAMException xe) {&lt;br /&gt;            System.err.println("XAM ERROR: " + xe.getMessage());&lt;br /&gt;            exitCode = 1;&lt;br /&gt;        } catch (IllegalArgumentException e) {&lt;br /&gt;            System.out.println(e.getMessage());&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;            exitCode = 1;&lt;br /&gt;        } catch (IOException e) {&lt;br /&gt;             System.err.println("IO ERROR: " + e.getMessage());&lt;br /&gt;             e.printStackTrace();&lt;br /&gt;             exitCode = 1;&lt;br /&gt;        } catch (Exception ex) {&lt;br /&gt;             ex.printStackTrace();&lt;br /&gt;             exitCode = 1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        System.exit((int) exitCode);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here is the set of fields, i.e those fields which start with &lt;em&gt;.xam.&lt;/em&gt; for the XAMLibrary object when the application is connected to an EMC Centera using EMC's XAM VIM.  It is followed by the set of fields, i.e. those fields starting with &lt;em&gt;.xsystem.&lt;/em&gt;, for an XSystem object which we create using this XAMLibrary object.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ java XamFieldIterator&lt;br /&gt;Connecting to XSystem snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea&lt;br /&gt;&lt;br /&gt;Enter prefix to filter results (blank for all): .xam&lt;br /&gt;&lt;br /&gt;.xam.log.component.filter   (application/vnd.snia.xam.string) NB RW   ""&lt;br /&gt;.xam.log.message.filter   (application/vnd.snia.xam.string) NB RW   ""&lt;br /&gt;.xam.log.max.rollovers   (application/vnd.snia.xam.int) NB RW   "1"&lt;br /&gt;.xam.log.max.size   (application/vnd.snia.xam.int) NB RW   "1048576"&lt;br /&gt;.xam.log.append   (application/vnd.snia.xam.boolean) NB RW   "false"&lt;br /&gt;.xam.log.format   (application/vnd.snia.xam.int) NB RW   "1"&lt;br /&gt;.xam.log.path   (application/vnd.snia.xam.string) NB RW   "xam.log"&lt;br /&gt;.xam.log.verbosity   (application/vnd.snia.xam.int) NB RW   "0"&lt;br /&gt;.xam.log.level   (application/vnd.snia.xam.int) NB RW   "0"&lt;br /&gt;&lt;br /&gt;Closed connection to XSystem&lt;br /&gt;&lt;br /&gt;$ java XamFieldIterator&lt;br /&gt;Connecting to XSystem snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea&lt;br /&gt;&lt;br /&gt;Enter prefix to filter results (blank for all): .xsystem&lt;br /&gt;&lt;br /&gt;.xsystem.auth.identity.authorization   (application/vnd.snia.xam.string) NB RO   "xam_challenge"&lt;br /&gt;.xsystem.auth.identity.authentication   (application/vnd.snia.xam.string) NB RO   "xam_challenge"&lt;br /&gt;.xsystem.limits.maxSizeOfXStream   (application/vnd.snia.xam.int) NB RO   "107374182400"&lt;br /&gt;.xsystem.limits.maxFieldsPerXSet   (application/vnd.snia.xam.int) NB RO   "9223372036854775807"&lt;br /&gt;.xsystem.identity   (application/vnd.snia.xam.string) NB RO   "EMC Centera, ID# 34372862-1dd2-11b2-aea0-f013836b5e75"&lt;br /&gt;.xsystem.auth.SASLmechanism.list.ANONYMOUS   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.SASLmechanism.list.PLAIN   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.SASLmechanism.default   (application/vnd.snia.xam.string) NB RO   "ANONYMOUS"&lt;br /&gt;.xsystem.time   (application/vnd.snia.xam.datetime) NB RO   "2009-5-28 15:10:42"&lt;br /&gt;.xsystem.auth.granule.list.read   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.write-application   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.write-system   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.create   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.delete   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.job   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.job-commit   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.auth.granule.list.hold   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.auth.granule.list.retention-event   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.job.list.xam.job.query   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.expiration   (application/vnd.snia.xam.int) NB RO   "-1"&lt;br /&gt;.xsystem.access   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.job.commit.supported   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.job.xam.job.query.continuance.supported   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.job.xam.job.query.level2.supported   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.job.xam.job.query.level1.supported   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.deletion.autodelete   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.deletion.shred   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.management.policy.default   (application/vnd.snia.xam.string) NB RO   "default"&lt;br /&gt;.xsystem.management.policy.list.default   (application/vnd.snia.xam.string) NB RO   "default"&lt;br /&gt;.xsystem.retention.duration.policy.list.0seconds   (application/vnd.snia.xam.string) NB RO   "0seconds"&lt;br /&gt;.xsystem.retention.duration.policy.list.10min   (application/vnd.snia.xam.string) NB RO   "10min"&lt;br /&gt;.xsystem.retention.duration.policy.list.1day   (application/vnd.snia.xam.string) NB RO   "1day"&lt;br /&gt;.xsystem.retention.duration.policy.list.1hr   (application/vnd.snia.xam.string) NB RO   "1hr"&lt;br /&gt;.xsystem.retention.duration.policy.list.30days   (application/vnd.snia.xam.string) NB RO   "30days"&lt;br /&gt;.xsystem.retention.duration.policy.list.60days   (application/vnd.snia.xam.string) NB RO   "60days"&lt;br /&gt;.xsystem.retention.duration.policy.list.CBR_EMail   (application/vnd.snia.xam.string) NB RO   "CBR_EMail"&lt;br /&gt;.xsystem.retention.duration.policy.list.CBR_Email   (application/vnd.snia.xam.string) NB RO   "CBR_Email"&lt;br /&gt;.xsystem.retention.duration.policy.list.CBR_PACS   (application/vnd.snia.xam.string) NB RO   "CBR_PACS"&lt;br /&gt;.xsystem.log.level   (application/vnd.snia.xam.int) NB RW   "0"&lt;br /&gt;.xsystem.log.verbosity   (application/vnd.snia.xam.int) NB RW   "0"&lt;br /&gt;.xsystem.log.path   (application/vnd.snia.xam.string) NB RW   "centera_vim.log"&lt;br /&gt;&lt;br /&gt;Closed connection to XSystem&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here are the corresponding outputs when the application instead connects to the SNIA XAM-SDK reference VIM which incidently is written completely in Java; hence the need for two different factory methods in our application.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ java XamFieldIterator -r&lt;br /&gt;Initializing VIM&lt;br /&gt;Loading test properties from file: xam.test.props&lt;br /&gt;Loading the VIM using the Java XAM Library.&lt;br /&gt;VIM Configuration contained in file: ../config/ReferenceVIM.config&lt;br /&gt;Connecting to XSystem snia-xam://SNIA_Reference_VIM!localhost?dir=/home/fpm/xam/xam_storage&lt;br /&gt;&lt;br /&gt;Enter prefix to filter results (blank for all): .xam&lt;br /&gt;.xam.apiLevel   (application/vnd.snia.xam.string) NB RW   "01.00.00"&lt;br /&gt;.xam.identity   (application/vnd.snia.xam.string) NB RW   "SNIA XAM Java Library v1.0"&lt;br /&gt;.xam.log.append   (application/vnd.snia.xam.boolean) NB RW   "false"&lt;br /&gt;.xam.log.level   (application/vnd.snia.xam.int) NB RW   "1"&lt;br /&gt;.xam.log.max.rollovers   (application/vnd.snia.xam.int) NB RW   "1"&lt;br /&gt;.xam.log.max.size   (application/vnd.snia.xam.int) NB RW   "10"&lt;br /&gt;.xam.log.path   (application/vnd.snia.xam.string) NB RW   "SNIA-XAM.log"&lt;br /&gt;.xam.log.verbosity   (application/vnd.snia.xam.int) NB RW   "1"&lt;br /&gt;.xam.vim.list.SNIA_Reference_VIM   (application/vnd.snia.xam.string) NB RW   "SNIA_Reference_VIM"&lt;br /&gt;&lt;br /&gt;Closed connection to XSystem&lt;br /&gt;&lt;br /&gt;$ java XamFieldIterator -r&lt;br /&gt;&lt;br /&gt;Initializing VIM&lt;br /&gt;Loading test properties from file: xam.test.props&lt;br /&gt;Loading the VIM using the Java XAM Library.&lt;br /&gt;VIM Configuration contained in file: ../config/ReferenceVIM.config&lt;br /&gt;Connecting to XSystem snia-xam://SNIA_Reference_VIM!localhost?dir=/home/fpm/xam/xam_storage&lt;br /&gt;&lt;br /&gt;Enter prefix to filter results (blank for all): .xsystem&lt;br /&gt;.xsystem.access   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.access.policy.list.read   (application/vnd.snia.xam.string) NB RO   "Read"&lt;br /&gt;.xsystem.access.policy.list.write-application   (application/vnd.snia.xam.string) NB RO   "Write-application"&lt;br /&gt;.xsystem.access.policy.list.write-system   (application/vnd.snia.xam.string) NB RO   "Write-system"&lt;br /&gt;.xsystem.auth.SASLmechanism.default   (application/vnd.snia.xam.string) NB RO   "PLAIN"&lt;br /&gt;.xsystem.auth.SASLmechanism.list.ANONYMOUS   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.SASLmechanism.list.PLAIN   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.expiration   (application/vnd.snia.xam.int) NB RO   "-1"&lt;br /&gt;.xsystem.auth.granule.list.create   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.delete   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.hold   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.job   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.job-commit   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.read   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.retention-event   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.write-application   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.granule.list.write-system   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.auth.identity.authentication   (application/vnd.snia.xam.string) NB RO   ""&lt;br /&gt;.xsystem.auth.identity.authorization   (application/vnd.snia.xam.string) NB RO   ""&lt;br /&gt;.xsystem.deletion.autodelete   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.deletion.shred   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.identity   (application/vnd.snia.xam.string) NB RO   "ultra.localdomain File System"&lt;br /&gt;.xsystem.job.commit.supported   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.job.list.xam.job.query   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.job.xam.job.query.continuance.supported   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.job.xam.job.query.level1.supported   (application/vnd.snia.xam.boolean) NB RO   "true"&lt;br /&gt;.xsystem.job.xam.job.query.level2.supported   (application/vnd.snia.xam.boolean) NB RO   "false"&lt;br /&gt;.xsystem.limits.maxFieldsPerXSet   (application/vnd.snia.xam.int) NB RO   "10000"&lt;br /&gt;.xsystem.limits.maxSizeOfXStream   (application/vnd.snia.xam.int) NB RO   "9223372036854775807"&lt;br /&gt;.xsystem.management.policy.default   (application/vnd.snia.xam.string) NB RO   ".org.snia.refvim.default.mgmt.policy"&lt;br /&gt;.xsystem.management.policy.list..org.snia.refvim.default.mgmt.policy   (application/vnd.snia.xam.string) NB RO   ".org.snia.refvim.default.mgmt.policy"&lt;br /&gt;.xsystem.time   (application/vnd.snia.xam.datetime) NB RO   "2009-5-29 10:24:0"&lt;br /&gt;&lt;br /&gt;Closed connection to XSystem&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;As you can see there are lots of interesting and potentially useful information available in the fields associated with a XAMLIbrary or XSystem object.  Hopefully this post has improved your knowledge of the mandated fields and the field namespace.&lt;br /&gt;&lt;br /&gt;Happy Independence Day!&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-1587264670659520885?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/1587264670659520885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/xam-mandated-fields.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1587264670659520885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1587264670659520885'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/xam-mandated-fields.html' title='XAM Mandated Fields'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-1734755731887416239</id><published>2009-06-24T16:47:00.003-04:00</published><updated>2009-08-19T09:38:40.357-04:00</updated><title type='text'></title><content type='html'>I have finally taken the plunge and moved my blog to Wordpress on my own website.&amp;nbsp; I had intended doing this many months ago but work kept getting in the way.&lt;br /&gt;&lt;br /&gt;The straw that broke the proverbial camel's back occurred yesterday when I wanted to change the theme of my blog to a more modern looking theme.&amp;nbsp; I followed Blogger's recommendations and exported all my posts and data to my desktop.&amp;nbsp; However it turns out that Blogger does not handle switching themes very well when you have a number of custom widgets.&amp;nbsp; Given that I was going to have to spend significant time fixing up things after a simple theme change, I decided that that time would be better spent switching to WordPress. &lt;br /&gt;&lt;br /&gt;The URL for my blog is &lt;a href='http://blog.fpmurphy.com'&gt;blog.fpmurphy.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It is a work in process at present&amp;nbsp;  I have imported most posts from Blogger and will do the minor cleanup required as a result of this import starting at the newest post and working back to the oldest post.&lt;br /&gt;&lt;br /&gt;I will continue to post a copy of my blog posts here because search engines seem to index this location more than my website.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-1734755731887416239?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/1734755731887416239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/i-have-finally-taken-plunge-and-moved.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1734755731887416239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1734755731887416239'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/i-have-finally-taken-plunge-and-moved.html' title=''/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-3109911648139139499</id><published>2009-06-20T18:15:00.059-04:00</published><updated>2009-06-22T22:40:10.611-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XSystem'/><category scheme='http://www.blogger.com/atom/ns#' term='SNIA'/><category scheme='http://www.blogger.com/atom/ns#' term='XSet'/><category scheme='http://www.blogger.com/atom/ns#' term='XOP'/><category scheme='http://www.blogger.com/atom/ns#' term='XStream'/><category scheme='http://www.blogger.com/atom/ns#' term='XAM'/><category scheme='http://www.blogger.com/atom/ns#' term='MIME'/><title type='text'>XAM Canonical Format</title><content type='html'>One of the key requirements for achieving long term data persistence is the ability to move data between archiving systems or, in the language of the SNIA &lt;span class='notranslate'&gt;&lt;a href='http://en.wikipedia.org/wiki/Xam'&gt;XAM&lt;/a&gt; (eXtensible Access Method)&lt;/span&gt; specification, moving &lt;span class='notranslate'&gt;XSets&lt;/span&gt; between &lt;span class='notranslate'&gt;XSystems&lt;/span&gt;.&lt;br /&gt; &lt;br /&gt;The &lt;span class='notranslate'&gt;XAM&lt;/span&gt; v1.0 specification supports this requirement by providing support for exporting and importing &lt;span class='notranslate'&gt;Xsets&lt;/span&gt;.&amp;nbsp; It specifies the methods used to export an &lt;span class='notranslate'&gt;XSet&lt;/span&gt; from an &lt;span class='notranslate'&gt;XSystem&lt;/span&gt;, the resultant &lt;span class='notranslate'&gt;XSet&lt;/span&gt; canonical data interchange format (package) and the methods used to import an &lt;span class='notranslate'&gt;Xset&lt;/span&gt; into an &lt;span class='notranslate'&gt;Xsystem&lt;/span&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;This post assumes that you are somewhat familiar with &lt;span class='notranslate'&gt;XAM&lt;/span&gt; and how to program to that &lt;a href='&lt;br /&gt;http://www.snia.org/forums/xam/technology/specs/'&gt;specification&lt;/a&gt; using Java.&amp;nbsp; It focuses on the format and content of the XSet canonical format package which consists of two main parts: an XML document which describes the policies, properties and streams of one or more XSets followed by the binary representation of the stream(s).&lt;br /&gt;&lt;br /&gt;The package format conforms to the 2005 &lt;span class='notranslate'&gt;W3C&lt;/span&gt; &lt;span class='notranslate'&gt;&lt;a href='http://www.w3.org/TR/xop10/'&gt;XML-binary Optimized Packaging&lt;/a&gt; (XOP)&lt;/span&gt; recommendation. To quote from the recommendation:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;XOP define a general purpose serialization mechanism for the XML Infoset with binary content that is not only applicable to SOAP and MIME packaging, but to any XML Infoset and any packaging mechanism. &lt;/blockquote&gt;If you are unfamiliar with &lt;span class='notranslate'&gt;XOP&lt;/span&gt;, and most people are, an article by &lt;span class='notranslate'&gt;Andrey Butov&lt;/span&gt; in the December 2005 issue of &lt;span class='notranslate'&gt;&lt;a href='http://www.ddj.com/web-development/184406347'&gt;Doctor Dobb's Journal&lt;/a&gt;&lt;/span&gt; contained a good introduction.&lt;br /&gt;&lt;br /&gt;More than one &lt;span class='notranslate'&gt;XSet&lt;/span&gt; can be contained in a &lt;span class='notranslate'&gt;package&lt;/span&gt;.&amp;nbsp; However the current &lt;span class='notranslate'&gt;XAM SDK&lt;/span&gt; reference implementation only supports one &lt;span class='notranslate'&gt;XSet&lt;/span&gt;.&amp;nbsp; The XML document (AKA the &lt;span class='notranslate'&gt;&lt;i&gt;XSet manifest&lt;/i&gt;&lt;/span&gt;) is a valid and well-formed &lt;span class='notranslate'&gt;XML&lt;/span&gt; document whose root element is &lt;span class='notranslate'&gt;&lt;i&gt;xsets&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; It can be parsed and manipulated using &lt;span class='notranslate'&gt;XSLT&lt;/span&gt; and other &lt;span class='notranslate'&gt;XML&lt;/span&gt; tools.&amp;nbsp; &lt;span class='notranslate'&gt;&lt;i&gt;Annex B&lt;/i&gt;&lt;/span&gt; of the &lt;span class='notranslate'&gt;XAM Architecture&lt;/span&gt; document contains an &lt;span class='notranslate'&gt;XML Schema Definition (&lt;a href='http://en.wikipedia.org/wiki/XML_schema'&gt;XSD&lt;/a&gt;)&lt;/span&gt; for the &lt;span class='notranslate'&gt;XSet manifest&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;In order to study the package format in more detail, I wrote a small Java application called &lt;span class='notranslate'&gt;&lt;i&gt;StoreHelloWorld&lt;/i&gt;&lt;/span&gt; which creates a new &lt;span class="notranslate"&gt;&lt;i&gt;XSet&lt;/i&gt;&lt;/span&gt; containing two &lt;span class="notranslate"&gt;&lt;i&gt;XStreams&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; The first &lt;span class="notranslate"&gt;&lt;i&gt;Xstream &lt;/i&gt;&lt;/span&gt; contains the source code for the ubiquitous &lt;span class="notranslate"&gt;&lt;i&gt;HelloWorld.java&lt;/i&gt;&lt;/span&gt; program.&amp;nbsp; The second &lt;span class="notranslate"&gt;&lt;i&gt;XStream&lt;/i&gt;&lt;/span&gt; contains the binary object &lt;span class="notranslate"&gt;&lt;i&gt;HelloWorld.class&lt;/i&gt;&lt;/span&gt; encoded to &lt;span class="notranslate"&gt;base64&lt;/span&gt; and with a &lt;span class="notranslate"&gt;MIME&lt;/span&gt; type of &lt;span class="notranslate"&gt;&lt;i&gt;application/base64&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Normally you should not encode an &lt;span class='notranslate'&gt;XStream&lt;/span&gt; but displaying binary files in a blog is problematic and hence the workaround.&lt;br /&gt;&lt;br /&gt;Here is the source code for &lt;span class='notranslate'&gt;&lt;i&gt;StoreHelloWorld&lt;/i&gt;&lt;/span&gt;. &lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;import java.io.BufferedOutputStream;&lt;br /&gt;import java.io.BufferedInputStream;&lt;br /&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.FileOutputStream;&lt;br /&gt;import java.io.FileNotFoundException;&lt;br /&gt;import java.io.FileWriter;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import java.util.Calendar;&lt;br /&gt;&lt;br /&gt;import org.snia.xam.XAMException;&lt;br /&gt;import org.snia.xam.XAMLibrary;&lt;br /&gt;import org.snia.xam.XSet;&lt;br /&gt;import org.snia.xam.XStream;&lt;br /&gt;import org.snia.xam.XSystem;&lt;br /&gt;import org.snia.xam.XUID;&lt;br /&gt;import org.snia.xam.util.XAMLibraryFactory;&lt;br /&gt;&lt;br /&gt;public class StoreHelloWorld {&lt;br /&gt;   private static XAMLibrary xamLib;&lt;br /&gt;   private static XSystem xSystem;&lt;br /&gt;   private static final int BUFFER_SIZE = 1024 * 128;&lt;br /&gt;&lt;br /&gt;    private static XUID storeExportFile(String filename) throws XAMException {&lt;br /&gt;        XUID xuid = null;&lt;br /&gt;&lt;br /&gt;        System.out.println("Create XSet ....");&lt;br /&gt;        XSet xSet = xSystem.createXSet(XSet.MODE_UNRESTRICTED);&lt;br /&gt;        xSet.createProperty("app.filename", true, "HelloWorld.");&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            System.out.println("Create XStream 1 ....");&lt;br /&gt;            BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream("HelloWorld.java"));&lt;br /&gt;            XStream xStream = xSet.createXStream("com.rhc.file.source", true, XAMLibrary.DEFAULT_MIME_TYPE);&lt;br /&gt;&lt;br /&gt;            byte[] buffer = new byte[BUFFER_SIZE];&lt;br /&gt;            long bytesRead = 0;&lt;br /&gt;&lt;br /&gt;            while((bytesRead = inputStream.read(buffer)) &gt; 0) {&lt;br /&gt;                long bytesPos = 0;&lt;br /&gt;                while(bytesPos &lt; bytesRead) {&lt;br /&gt;                    long bytesWrite = xStream.write(buffer, bytesPos, bytesRead - bytesPos);&lt;br /&gt;                    bytesPos += bytesWrite;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            inputStream.close();&lt;br /&gt;            xStream.close();&lt;br /&gt;        } catch (FileNotFoundException fe) {&lt;br /&gt;            throw new IllegalArgumentException("Could not open HelloWorld.java for reading");&lt;br /&gt;        } catch (IOException ioe) {&lt;br /&gt;            System.err.println("Error reading from HelloWorld.java");&lt;br /&gt;            ioe.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            System.out.println("Create XStream 2 ....");&lt;br /&gt;&lt;br /&gt;            InputStream inputStream = new Base64.InputStream(new FileInputStream("HelloWorld.class"), Base64.ENCODE | Base64.DO_BREAK_LINES);&lt;br /&gt;            XStream xStream = xSet.createXStream("com.rhc.file.binary", true, "application/base64");&lt;br /&gt;&lt;br /&gt;            byte[] buffer = new byte[BUFFER_SIZE];&lt;br /&gt;            long bytesRead = 0;&lt;br /&gt;&lt;br /&gt;            while((bytesRead = inputStream.read(buffer)) &gt; 0) {&lt;br /&gt;                long bytesPos = 0;&lt;br /&gt;                while(bytesPos &lt; bytesRead) {&lt;br /&gt;                    long bytesWrite = xStream.write(buffer, bytesPos, bytesRead - bytesPos);&lt;br /&gt;                    bytesPos += bytesWrite;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            inputStream.close();&lt;br /&gt;            xStream.close();&lt;br /&gt;        } catch (FileNotFoundException fe) {&lt;br /&gt;            throw new IllegalArgumentException("Could not open HelloWorld.class for reading");&lt;br /&gt;        } catch (IOException ioe) {&lt;br /&gt;            System.err.println("Error reading from HelloWorld.class");&lt;br /&gt;            ioe.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;       System.out.println("Commit XSet .... ");&lt;br /&gt;       xuid = xSet.commit();&lt;br /&gt;       System.out.println("Assigned XUID: " + xuid.toString());&lt;br /&gt;&lt;br /&gt;       System.out.println("Close XSet .... ");&lt;br /&gt;       xSet.close();&lt;br /&gt;&lt;br /&gt;       File saveFile = new File(filename);&lt;br /&gt;       try {&lt;br /&gt;           System.out.println("\nOpen XSet .... ");&lt;br /&gt;           xSet = xSystem.openXSet(xuid, XSet.MODE_READ_ONLY);&lt;br /&gt;&lt;br /&gt;           BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(saveFile));&lt;br /&gt;&lt;br /&gt;           System.out.println("Open XStream for export ....");&lt;br /&gt;           XStream xStream = xSet.openExportXStream();&lt;br /&gt;&lt;br /&gt;           byte[] buffer = new byte[BUFFER_SIZE];&lt;br /&gt;           long bytesRead = 0;&lt;br /&gt;&lt;br /&gt;           System.out.println("Retrieve data .... ");&lt;br /&gt;           while((bytesRead = xStream.read(buffer)) &gt; 0) {&lt;br /&gt;               outputStream.write(buffer, 0, (int)bytesRead);&lt;br /&gt;           }&lt;br /&gt;           xStream.close();&lt;br /&gt;           outputStream.close();&lt;br /&gt;&lt;br /&gt;           System.out.println("Close XSet .... ");&lt;br /&gt;           xSet.close();&lt;br /&gt;        } catch (IOException ioe) {&lt;br /&gt;            System.err.println("Error writing to " + saveFile);&lt;br /&gt;            ioe.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return (xuid);&lt;br /&gt;   }&lt;br /&gt; &lt;br /&gt;   public static void main(String[] args) {&lt;br /&gt;       String xri = XRIstring.get();&lt;br /&gt;       long exitCode = 0;&lt;br /&gt;&lt;br /&gt;       InputStreamReader inputReader = new InputStreamReader(System.in);&lt;br /&gt;       BufferedReader stdin = new BufferedReader(inputReader);&lt;br /&gt;&lt;br /&gt;       try {&lt;br /&gt;           xamLib = XAMLibraryFactory.newXAMLibrary();&lt;br /&gt;&lt;br /&gt;           if (xri == null ) {&lt;br /&gt;               System.out.print("Enter Xsystem address: ");&lt;br /&gt;               String answer = stdin.readLine();&lt;br /&gt;               if (!answer.equals(""))&lt;br /&gt;                  xri = answer;&lt;br /&gt;               else&lt;br /&gt;                  System.exit(0);&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           System.out.println("Connecting to XSystem: " + xri );&lt;br /&gt;           xSystem = xamLib.connect(xri);&lt;br /&gt;&lt;br /&gt;           System.out.print("Name of export file: ");&lt;br /&gt;           String filename = stdin.readLine();&lt;br /&gt;           if (filename.equals(""))&lt;br /&gt;               System.exit(0);&lt;br /&gt;&lt;br /&gt;           XUID xuid = storeExportFile(filename);&lt;br /&gt;&lt;br /&gt;           xSystem.close();&lt;br /&gt;           System.out.println("\nClosed connection to XSystem");&lt;br /&gt;&lt;br /&gt;           inputReader.close();&lt;br /&gt;           stdin.close();&lt;br /&gt;&lt;br /&gt;       } catch (XAMException xe) {&lt;br /&gt;           exitCode = xe.getStatusCode();&lt;br /&gt;           System.err.println(&lt;br /&gt;               "XAM Error occured: " + xe.getMessage() + "(" + exitCode + ")");&lt;br /&gt;       } catch (IOException e) {&lt;br /&gt;           System.out.println("I/O Error occurred: " + e.getMessage());&lt;br /&gt;           e.printStackTrace();&lt;br /&gt;           exitCode = 1;&lt;br /&gt;       } catch (IllegalArgumentException e) {&lt;br /&gt;           System.out.println(e.getMessage());&lt;br /&gt;           e.printStackTrace();&lt;br /&gt;           exitCode = 1;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       System.exit((int) exitCode);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/span&gt;Rather than hard code an &lt;span class='notranslate'&gt;XRI (XAM Resource Identifier)&lt;/span&gt; in each &lt;span class='notranslate'&gt;XAM&lt;/span&gt; application, I use a separate Java class (&lt;span class='notranslate'&gt;&lt;i&gt;XRIstring&lt;/i&gt;&lt;/span&gt;) to read in the &lt;span class='notranslate'&gt;XRI&lt;/span&gt; from the standard &lt;span class='notranslate'&gt;XAM&lt;/span&gt; properties file &lt;span class='notranslate'&gt;&lt;i&gt;xam.properties&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I know that this is not kosher according to the current &lt;span class='notranslate'&gt;XAM&lt;/span&gt; specification but, in my humble opinion, this is the natural location for storing this string as most people will not be connecting simultaneously to multiple &lt;span class='notranslate'&gt;XSystems&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Here is the source for that Java class.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.FileNotFoundException;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;&lt;br /&gt;public class XRIstring&lt;br /&gt;{&lt;br /&gt;   private static Properties props;&lt;br /&gt;   private static String XRI = ".xam.config.xri";&lt;br /&gt;   private static String xri = null;&lt;br /&gt;&lt;br /&gt;   static {&lt;br /&gt;&lt;br /&gt;       props = new Properties();&lt;br /&gt;       try {&lt;br /&gt;           props.load(new FileInputStream("xam.properties"));&lt;br /&gt;&lt;br /&gt;           xri = props.getProperty(XRI);&lt;br /&gt;           if (xri != null)&lt;br /&gt;               System.out.println("XSystem Address: " + xri );&lt;br /&gt;&lt;br /&gt;       } catch (FileNotFoundException e) {&lt;br /&gt;          System.err.println("Could not find properties file. XSystem address must be manually entered");&lt;br /&gt;       } catch (IOException e) {&lt;br /&gt;          System.err.println("Could not access properties file. XSystem address must be manually entered");&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public static String get()&lt;br /&gt;   {&lt;br /&gt;        return(xri);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;This application also uses Robert Harder's popular &lt;span class='notranslate'&gt;&lt;i&gt;Base64&lt;/i&gt;&lt;/span&gt; class which is available &lt;a href='http://iharder.sourceforge.net/current/java/base64/'&gt;here&lt;/a&gt;.&amp;nbsp; Assuming your &lt;span class='notranslate'&gt;CLASSPATH&lt;/span&gt; is set up correctly to find the XAM libraries, here is the output from &lt;span class='notranslate'&gt;&lt;i&gt;StoreHelloWorld&lt;/i&gt;&lt;/span&gt; when you build and run it.&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;$ javac StoreHelloWorld.java XRIstring.java Base64.java&lt;br /&gt;&lt;br /&gt;$ java StoreHelloWorld&lt;br /&gt;Connecting to XSystem: snia-xam://centera_vim!XXX.XXX.XXX.XXX?/home/fpm/xam/xamconnect.pea&lt;br /&gt;Name of export file: sample&lt;br /&gt;Create XSet ....&lt;br /&gt;Create XStream 1 ....&lt;br /&gt;Create XStream 2 ....&lt;br /&gt;Commit XSet ....&lt;br /&gt;Assigned XUID: AAAEcwA9S8c0UTVHVDdRSDRSUU9VZUVWMkEyTTJGUUw2UUlHNDE0N1ZTMzFKTzFURkxWUjVKNkFDVEo2Ng==&lt;br /&gt;Close XSet ....&lt;br /&gt;&lt;br /&gt;Open XSet for export ....&lt;br /&gt;Retrieve data ....&lt;br /&gt;Close XSet ....&lt;br /&gt;&lt;br /&gt;Closed connection to XSystem&lt;br /&gt;$ &lt;/pre&gt;&lt;/div&gt;&lt;/span&gt;Here is the contents of the export file (&lt;span class="notranslate"&gt;&lt;i&gt;sample&lt;/i&gt;&lt;/span&gt;) which was created.&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;Content-Type: Multipart/Related;boundary="___EMC_XOP_BOUNDARY_START___1245537694___EMC_XOP_BOUNDARY_END___";&lt;br /&gt;type="application/xop+xml";&lt;br /&gt;start="&amp;lt;canonicalxset.xml@snia.org&amp;gt;";&lt;br /&gt;start-info="text/xml"&lt;br /&gt;Content-Description: EMC XSet Export Package&lt;br /&gt;&lt;br /&gt;--___EMC_XOP_BOUNDARY_START___1245537694___EMC_XOP_BOUNDARY_END___&lt;br /&gt;Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"&lt;br /&gt;Content-Transfer-Encoding: 8bit&lt;br /&gt;Content-ID: &amp;lt;canonicalxset.xml@snia.org&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;xsets xmlns="http://www.snia.org/2007/xam/export"&lt;br /&gt;xmlns:xop="http://www.w3.org/2004/08/xop/include"&lt;br /&gt;xmlns:emcannotations="http://www.emc.com/2008/01/centera/emcannotations"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xsi:schemaLocation="http://www.snia.org/2007/xam/export XAMCanonicalXSetDefinition.xsd&lt;br /&gt;http://www.w3.org/2004/08/xop/include http://www.w3.org/2004/08/xop/include&lt;br /&gt;http://www.emc.com/2008/01/centera/emcannotations emcannotations.xsd "&amp;gt;&lt;br /&gt;&amp;lt;version&amp;gt;1.0.0&amp;lt;/version&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;policies&amp;gt;&lt;br /&gt;  &amp;lt;policy name=".xsystem.management.policy.list.default" type="application/vnd.snia.xam.string" readOnly="true" binding="false" length="7" &amp;gt;&lt;br /&gt;    &amp;lt;value&amp;gt;default&amp;lt;/value&amp;gt;&lt;br /&gt;  &amp;lt;/policy&amp;gt;&lt;br /&gt;&amp;lt;/policies&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;xset&amp;gt;&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;    &amp;lt;property name="app.filename" type="application/vnd.snia.xam.string" readOnly="false" binding="true" length="11"  emcannotations:seqno="0"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;HelloWorld.&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.time.creation" type="application/vnd.snia.xam.datetime" readOnly="true" binding="true" length="24"  emcannotations:seqno="3"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009-06-20T22:20:19.000Z&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.time.access" type="application/vnd.snia.xam.datetime" readOnly="true" binding="false" length="24"  emcannotations:seqno="4"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009-06-20T22:20:21.000Z&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.time.commit" type="application/vnd.snia.xam.datetime" readOnly="true" binding="false" length="24"  emcannotations:seqno="5"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009-06-20T22:20:21.000Z&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.time.residency" type="application/vnd.snia.xam.datetime" readOnly="true" binding="false" length="24"  emcannotations:seqno="6"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009-06-20T22:20:21.000Z&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.xuid" type="application/vnd.snia.xam.xuid" readOnly="true" binding="false" length="61"  emcannotations:seqno="7"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;AAAEcwA9S8c0UTVHVDdRSDRSUU9VZUVWMkEyTTJGUUw2UUlHNDE0N1ZTMzFKTzFURkxWUjVKNkFDVEo2Ng==&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.time.xuid" type="application/vnd.snia.xam.datetime" readOnly="true" binding="true" length="24"  emcannotations:seqno="8"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009-06-20T22:20:21.000Z&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.retention.list.base" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="4"  emcannotations:seqno="9"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;base&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.retention.base.enabled" type="application/vnd.snia.xam.boolean" readOnly="true" binding="true" length="1"  emcannotations:seqno="10"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;true&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.retention.base.duration" type="application/vnd.snia.xam.int" readOnly="true" binding="true" length="8"  emcannotations:seqno="11"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.retention.base.starttime" type="application/vnd.snia.xam.datetime" readOnly="true" binding="true" length="24"  emcannotations:seqno="12"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009-06-20T22:20:19.000Z&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.hold" type="application/vnd.snia.xam.boolean" readOnly="true" binding="false" length="1"  emcannotations:seqno="13"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;false&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".xset.management.policy" type="application/vnd.snia.xam.string" readOnly="true" binding="false" length="7"  emcannotations:seqno="14"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;default&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.creation.poolid" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="39"  emcannotations:seqno="15"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;34372862-1dd2-11b2-aea0-f013836b5e75-10&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.retention.base.enabled" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="4"  emcannotations:seqno="16"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;true&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.sdk.version" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="7"  emcannotations:seqno="17"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;4.0.672&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.modification.poolid" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="39"  emcannotations:seqno="18"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;34372862-1dd2-11b2-aea0-f013836b5e75-10&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.retention.period" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="1"  emcannotations:seqno="19"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.type" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="11"  emcannotations:seqno="20"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;xam.binding&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.name" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="29"  emcannotations:seqno="21"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;EMC Centera Binding XSet Clip&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.creation.date" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="23"  emcannotations:seqno="22"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009.06.20 22:20:19 GMT&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.modification.date" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="23"  emcannotations:seqno="23"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2009.06.20 22:20:21 GMT&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.creation.profile" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="13"  emcannotations:seqno="24"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;xam_challenge&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.modification.profile" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="13"  emcannotations:seqno="25"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;xam_challenge&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.numfiles" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="1"  emcannotations:seqno="26"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;2&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.totalsize" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="3"  emcannotations:seqno="27"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;731&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.refid" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="26"  emcannotations:seqno="28"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;6T90EGBR9LE5TFLVR5J6ACTJ66&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.clusterid" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="36"  emcannotations:seqno="29"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;34372862-1dd2-11b2-aea0-f013836b5e75&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.prev.clip" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="0"  emcannotations:seqno="30"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.clip.naming.scheme" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="3"  emcannotations:seqno="31"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;MD5&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.meta.standard.binding.numtags" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="1"  emcannotations:seqno="32"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;3&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.hidden.nonbinding.clipid" type="application/vnd.snia.xam.string" readOnly="true" binding="false" length="4"  emcannotations:seqno="33"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;NULL&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=".vnd.com.emc.centera.hidden.binding.clipid" type="application/vnd.snia.xam.string" readOnly="true" binding="true" length="53"  emcannotations:seqno="34"  &amp;gt;&lt;br /&gt;      &amp;lt;value&amp;gt;4Q5GT7QH4RQOUeEV2A2M2FQL6QIG4147VS31JO1TFLVR5J6ACTJ66&amp;lt;/value&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&amp;lt;xstreams&amp;gt;&lt;br /&gt;  &amp;lt;xstream name="com.rhc.file.source" type="application/octet-stream" readOnly="false" binding="true" length="156"  emcannotations:seqno="1"  &amp;gt;&lt;br /&gt;    &amp;lt;xop:Include href='cid:com.rhc.file.source' /&amp;gt;&lt;br /&gt;    &amp;lt;emcannotations:emcannotation emcannotations:embedded="false" &amp;gt;&lt;br /&gt;      &amp;lt;emcannotations:emcblobannotation emcannotations:blobguid="1OROBIQ8CLBN3x8HRFRPNS7UV61G4147VS30JN0TFLVR5J6ACTJ66" emcannotations:offset="0" emcannotations:length="156" /&amp;gt;&lt;br /&gt;    &amp;lt;/emcannotations:emcannotation&amp;gt;&lt;br /&gt;  &amp;lt;/xstream&amp;gt;&lt;br /&gt;  &amp;lt;xstream name="com.rhc.file.binary" type="application/base64" readOnly="false" binding="true" length="575"  emcannotations:seqno="2"  &amp;gt;&lt;br /&gt;    &amp;lt;xop:Include href='cid:com.rhc.file.binary' /&amp;gt;&lt;br /&gt;    &amp;lt;emcannotations:emcannotation emcannotations:embedded="false" &amp;gt;&lt;br /&gt;      &amp;lt;emcannotations:emcblobannotation emcannotations:blobguid="09D943LSJ49S2xFF94NIQ5B10MGG4147VS31HG0TFLVR5J6ACTJ66" emcannotations:offset="0" emcannotations:length="575" /&amp;gt;&lt;br /&gt;    &amp;lt;/emcannotations:emcannotation&amp;gt;&lt;br /&gt;  &amp;lt;/xstream&amp;gt;&lt;br /&gt;&amp;lt;/xstreams&amp;gt;&lt;br /&gt;&amp;lt;/xset&amp;gt;&lt;br /&gt;&amp;lt;/xsets&amp;gt;&lt;br /&gt;&lt;br /&gt;--___EMC_XOP_BOUNDARY_START___1245537694___EMC_XOP_BOUNDARY_END___&lt;br /&gt;Content-Type: text/text&lt;br /&gt;Content-Transfer-Encoding: text&lt;br /&gt;Content-ID: &amp;lt;TOC&amp;gt;&lt;br /&gt;&lt;br /&gt;Offset of AAAEcwA9S8c0UTVHVDdRSDRSUU9VZUVWMkEyTTJGUUw2UUlHNDE0N1ZTMzFKTzFURkxWUjVKNkFDVEo2Ng==:com.rhc.file.source: 10955                                                                                                                                                                                                                                                  &lt;br /&gt;Offset of AAAEcwA9S8c0UTVHVDdRSDRSUU9VZUVWMkEyTTJGUUw2UUlHNDE0N1ZTMzFKTzFURkxWUjVKNkFDVEo2Ng==:com.rhc.file.binary: 11285                                                                                                                                                                                                                                                  &lt;br /&gt;&lt;br /&gt;--___EMC_XOP_BOUNDARY_START___1245537694___EMC_XOP_BOUNDARY_END___&lt;br /&gt;Content-Type: application/octet-stream&lt;br /&gt;Content-Transfer-Encoding: binary&lt;br /&gt;Content-ID: com.rhc.file.source&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * HelloWorld.java&lt;br /&gt; *&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;public class HelloWorld {&lt;br /&gt;    public static void main(String[] args){&lt;br /&gt;       System.out.println("Hello World!");&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;--___EMC_XOP_BOUNDARY_START___1245537694___EMC_XOP_BOUNDARY_END___&lt;br /&gt;Content-Type: application/base64&lt;br /&gt;Content-Transfer-Encoding: binary&lt;br /&gt;Content-ID: com.rhc.file.binary&lt;br /&gt;&lt;br /&gt;yv66vgAAADIAHQoABgAPCQAQABEIABIKABMAFAcAFQcAFgEABjxpbml0PgEAAygpVgEABENvZGUB&lt;br /&gt;AA9MaW5lTnVtYmVyVGFibGUBAARtYWluAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEAClNvdXJj&lt;br /&gt;ZUZpbGUBAA9IZWxsb1dvcmxkLmphdmEMAAcACAcAFwwAGAAZAQAMSGVsbG8gV29ybGQhBwAaDAAb&lt;br /&gt;ABwBAApIZWxsb1dvcmxkAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANv&lt;br /&gt;dXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRs&lt;br /&gt;bgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACAABAAkAAAAdAAEAAQAA&lt;br /&gt;AAUqtwABsQAAAAEACgAAAAYAAQAAAAYACQALAAwAAQAJAAAAJQACAAEAAAAJsgACEgO2AASxAAAA&lt;br /&gt;AQAKAAAACgACAAAACAAIAAkAAQANAAAAAgAO&lt;br /&gt;--___EMC_XOP_BOUNDARY_START___1245537694___EMC_XOP_BOUNDARY_END___--&lt;/pre&gt;&lt;/div&gt;As you can see this export package is fairly large even though I am only storing two small &lt;span class='notranslate'&gt;XStreams&lt;/span&gt; in the &lt;span class='notranslate'&gt;XSet&lt;/span&gt; which I created.&lt;br /&gt;&lt;br /&gt;The &lt;span class='notranslate'&gt;XSet manifest&lt;/span&gt; is everything between the &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;xsets&amp;gt;&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;/xsets&amp;gt;&lt;/i&gt;&lt;/span&gt; tags.&amp;nbsp; It appears to be a valid and well formed XML document although I have not formally checked it.&lt;br /&gt;&lt;br /&gt;The first section, i.e. the &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;policies&amp;gt;&lt;/i&gt;&lt;/span&gt; section, lists the &lt;span class='notranslate'&gt;XSystem&lt;/span&gt; policies that are in effect for the included &lt;span class='notranslate'&gt;XSet(s)&lt;/span&gt;.&amp;nbsp; Here the policy is set to the default policy for the &lt;span class='notranslate'&gt;Xsystem&lt;/span&gt; from which I exported the &lt;span class='notranslate'&gt;Xset&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;It is followed by a section whose top element is &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;xset&amp;gt;&lt;/i&gt;&lt;/span&gt; which details the properties and &lt;span class='notranslate'&gt;XStream(s)&lt;/span&gt; for a single &lt;span class='notranslate'&gt;XSet&lt;/span&gt;.&amp;nbsp; Each &lt;span class='notranslate'&gt;XSet&lt;/span&gt; property element contains the following attributes: &lt;span class='notranslate'&gt;&lt;i&gt;type&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;readonly&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;binding&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;length&lt;/i&gt;&lt;/span&gt;.&amp;nbsp;  Each &lt;span class='notranslate'&gt;XStream&lt;/span&gt; is mapped to an &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;xstream&amp;gt;&lt;/i&gt;&lt;/span&gt; element which contains a child element &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;xop:include&amp;gt;&lt;/i&gt;&lt;/span&gt; which contains the &lt;span class='notranslate'&gt;&lt;i&gt;content-id&lt;/i&gt;&lt;/span&gt; to the corresponding &lt;span class='notranslate'&gt;MIME&lt;/span&gt; part containing the actual contents of the &lt;span class='notranslate'&gt;XStream&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;As you can see the actual contents of an &lt;span class='notranslate'&gt;XStream&lt;/span&gt; is included as a &lt;span class='notranslate'&gt;MIME&lt;/span&gt; attachment after the &lt;span class='notranslate'&gt;XSet manifest&lt;/span&gt;.&amp;nbsp; As an aside, note that there is no requirement for an &lt;span class='notranslate'&gt;XStream&lt;/span&gt; to verify that its contents actually match the declared &lt;span class='notranslate'&gt;MIME&lt;/span&gt; type.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The first &lt;span class='notranslate'&gt;MIME&lt;/span&gt; attachment shown above (AKA the &lt;span class='notranslate'&gt;&lt;i&gt;root&lt;/i&gt; MIME&lt;/span&gt;) lists the offsets of each of the two &lt;span class='notranslate'&gt;XStreams&lt;/span&gt;.&amp;nbsp; If an &lt;span class='notranslate'&gt;XSet&lt;/span&gt; does not contain an &lt;span class='notranslate'&gt;XStream&lt;/span&gt;, then there are no &lt;span class='notranslate'&gt;MIME&lt;/span&gt; attachments.&amp;nbsp; Other than the root &lt;span class='notranslate'&gt;MIME&lt;/span&gt; attachment the order of the &lt;span class='notranslate'&gt;MIME&lt;/span&gt; attachments is not significant.&amp;nbsp; The &lt;span class='notranslate'&gt;MIME&lt;/span&gt; attachments conform to the requirements of the &lt;span class='notranslate'&gt;MIME&lt;/span&gt; Multipart/Related Content-type specification (&lt;span class='notranslate'&gt;&lt;a href='http://www.ietf.org/rfc/rfc2387.txt'&gt;RFC 2387&lt;/a&gt;&lt;span&gt;). &lt;br /&gt;&lt;br /&gt;Here is the export package generated when &lt;span class='notranslate'&gt;&lt;i&gt;StoreHelloWolld&lt;/i&gt;&lt;/span&gt; was targeted at the &lt;span class='notranslate'&gt;SNIA XAM&lt;/span&gt; reference &lt;span class='notranslate'&gt;VIM (Vendor Interface Module)&lt;/span&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;Content-Type: Multipart/Related;boundary="--SNIA_REFERENCE_VIM_MIME_BOUNDARY_2009-06-22T21:13:44.330-05:00.XZY_+";type="application/xop+xml";start="&amp;lt;canonicalxset.xml@snia.org&amp;gt;";start-info="text/xml"&lt;br /&gt;Content-Description:Export of XSet: AAA6AwAePKwxMjQ1NzIzMjI0Mjc4ATTLJDRoe2iJ&lt;br /&gt;&lt;br /&gt;----SNIA_REFERENCE_VIM_MIME_BOUNDARY_2009-06-22T21:13:44.330-05:00.XZY_+&lt;br /&gt;&lt;br /&gt;Content-Type:application/xop+xml;    charset="UTF-8";    type="text/xml"&lt;br /&gt;Content-Transfer-Encoding:8bit&lt;br /&gt;Content-ID:&amp;lt;canonicalxset.xml@snia.org&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;xsets xsi:schemaLocation="http://www.snia.org/2007/xam/export/XAMCanonicalXSetDefinition.xsd" xmlns="http://www.snia.org/2007/xam/export" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xop="http://www.w3.org/2004/08/xop/include"&amp;gt;&lt;br /&gt;&amp;lt;version&amp;gt;1.0.0&amp;lt;/version&gt;&lt;br /&gt;&amp;lt;xset&amp;gt;&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.hold" type="application/vnd.snia.xam.boolean" binding="false" readOnly="true" length="1"&amp;gt;&lt;br /&gt;        &amp;lt;boolean&amp;gt;false&amp;lt;/boolean&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.management.policy" type="application/vnd.snia.xam.string" binding="true" readOnly="true" length="36"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;.org.snia.refvim.default.mgmt.policy&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.retention.base.enabled" type="application/vnd.snia.xam.boolean" binding="true" readOnly="true" length="1"&amp;gt;&lt;br /&gt;        &amp;lt;boolean&amp;gt;true&amp;lt;/boolean&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.retention.base.starttime" type="application/vnd.snia.xam.datetime" binding="true" readOnly="true" length="29"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;2009-06-22T21:13:44.276-05:00&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.retention.list.base" type="application/vnd.snia.xam.string" binding="true" readOnly="true" length="4"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;base&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.retention.list.event" type="application/vnd.snia.xam.string" binding="true" readOnly="true" length="5"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;event&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.time.access" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;2009-06-22T21:13:44.276-05:00&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.time.commit" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;2009-06-22T21:13:44.276-05:00&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.time.creation" type="application/vnd.snia.xam.datetime" binding="true" readOnly="true" length="29"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;2009-06-22T21:13:44.225-05:00&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.time.xuid" type="application/vnd.snia.xam.datetime" binding="false" readOnly="true" length="29"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;2009-06-22T21:13:44.276-05:00&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name=".xset.xuid" type="application/vnd.snia.xam.xuid" binding="true" readOnly="true" length="30"&amp;gt;&lt;br /&gt;        &amp;lt;xuid&amp;gt;AAA6AwAePKwxMjQ1NzIzMjI0Mjc4ATTLJDRoe2iJ&amp;lt;/xuid&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;property name="app.filename" type="application/vnd.snia.xam.string" binding="true" readOnly="false" length="11"&amp;gt;&lt;br /&gt;        &amp;lt;string&amp;gt;HelloWorld.&amp;lt;/string&gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&amp;lt;xstreams&amp;gt;&lt;br /&gt;&amp;lt;xstream name="com.rhc.file.binary" type="application/base64" binding="true" readOnly="false" length="575"&amp;gt;&lt;br /&gt;        &amp;lt;org.snia.refvim.xstream_data&amp;gt;XStream_8508062132085140723.data&amp;lt;/org.snia.refvim.xstream_data&gt;&lt;br /&gt;&amp;lt;xop:Include href="cid:com.rhc.file.binary@snia.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/&amp;gt;&lt;br /&gt;&amp;lt;/xstream&amp;gt;&lt;br /&gt;&amp;lt;xstream name="com.rhc.file.source" type="application/octet-stream" binding="true" readOnly="false" length="156"&amp;gt;&lt;br /&gt;        &amp;lt;org.snia.refvim.xstream_data&amp;gt;XStream_3869980320333904649.data&amp;lt;/org.snia.refvim.xstream_data&gt;&lt;br /&gt;&amp;lt;xop:Include href="cid:com.rhc.file.source@snia.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/&amp;gt;&lt;br /&gt;&amp;lt;/xstream&amp;gt;&lt;br /&gt;&amp;lt;/xstreams&amp;gt;&lt;br /&gt;&amp;lt;/xset&amp;gt;&lt;br /&gt;&amp;lt;/xsets&amp;gt;&lt;br /&gt;----SNIA_REFERENCE_VIM_MIME_BOUNDARY_2009-06-22T21:13:44.330-05:00.XZY_+&lt;br /&gt;&lt;br /&gt;Content-Type:text/text&lt;br /&gt;Content-Transfer-Encoding:text&lt;br /&gt;Content-ID:&amp;lt;TOC&amp;gt;&lt;br /&gt;Offset of AAA6AwAePKwxMjQ1NzIzMjI0Mjc4ATTLJDRoe2iJ:com.rhc.file.binary@snia.org:3948&lt;br /&gt;Offset of AAA6AwAePKwxMjQ1NzIzMjI0Mjc4ATTLJDRoe2iJ:com.rhc.file.source@snia.org:4706&lt;br /&gt;&lt;br /&gt;----SNIA_REFERENCE_VIM_MIME_BOUNDARY_2009-06-22T21:13:44.330-05:00.XZY_+&lt;br /&gt;&lt;br /&gt;Content-Type:application/base64&lt;br /&gt;Content-Transfer-Encoding:binary&lt;br /&gt;Content-ID:&amp;lt;com.rhc.file.binary@snia.org&amp;gt;&lt;br /&gt;&lt;br /&gt;yv66vgAAADIAHQoABgAPCQAQABEIABIKABMAFAcAFQcAFgEABjxpbml0PgEAAygpVgEABENvZGUB&lt;br /&gt;AA9MaW5lTnVtYmVyVGFibGUBAARtYWluAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEAClNvdXJj&lt;br /&gt;ZUZpbGUBAA9IZWxsb1dvcmxkLmphdmEMAAcACAcAFwwAGAAZAQAMSGVsbG8gV29ybGQhBwAaDAAb&lt;br /&gt;ABwBAApIZWxsb1dvcmxkAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANv&lt;br /&gt;dXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRs&lt;br /&gt;bgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACAABAAkAAAAdAAEAAQAA&lt;br /&gt;AAUqtwABsQAAAAEACgAAAAYAAQAAAAYACQALAAwAAQAJAAAAJQACAAEAAAAJsgACEgO2AASxAAAA&lt;br /&gt;AQAKAAAACgACAAAACAAIAAkAAQANAAAAAgAO&lt;br /&gt;&lt;br /&gt;----SNIA_REFERENCE_VIM_MIME_BOUNDARY_2009-06-22T21:13:44.330-05:00.XZY_+&lt;br /&gt;&lt;br /&gt;Content-Type:application/octet-stream&lt;br /&gt;Content-Transfer-Encoding:binary&lt;br /&gt;Content-ID:&amp;lt;com.rhc.file.source@snia.org&amp;gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * HelloWorld.java&lt;br /&gt; *&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;public class HelloWorld {&lt;br /&gt;    public static void main(String[] args){&lt;br /&gt;       System.out.println("Hello World!");&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;----SNIA_REFERENCE_VIM_MIME_BOUNDARY_2009-06-22T21:13:44.330-05:00.XZY_+--&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;As you can see this export package is considerably more compact then the previous export package generated when I used the &lt;span class='notranslate'&gt;&lt;a href='http://www.emc.com/products/family/emc-centera-family.htm'&gt;EMC Centera&lt;/a&gt; XAM VIM&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Well, that is about all for now.&amp;nbsp; Hopefully this post was useful to you if you are just coming up to speed on &lt;span class="notranslate"&gt;XAM&lt;/span&gt; and wondering how to import and export &lt;span class='notranslate'&gt;XSets&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;BTW, Happy Father's Day to all dads who may be reading this post.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-3109911648139139499?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/3109911648139139499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/xam-and-xop.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3109911648139139499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3109911648139139499'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/xam-and-xop.html' title='XAM Canonical Format'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-2212036591124489889</id><published>2009-06-15T10:31:00.032-04:00</published><updated>2009-06-17T15:32:45.025-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SNIA'/><category scheme='http://www.blogger.com/atom/ns#' term='XAM'/><category scheme='http://www.blogger.com/atom/ns#' term='Fedora 11'/><category scheme='http://www.blogger.com/atom/ns#' term='Extended Attributes'/><title type='text'>Fedora 11 New Extended File Attributes Namespace</title><content type='html'>I am experimenting with &lt;a href='http://en.wikipedia.org/wiki/Xam'&gt;XAM&lt;/a&gt; (&lt;span class='notranslate'&gt;&lt;i&gt;eXtensible Access Method&lt;/i&gt;&lt;/span&gt;), which is a storage standard developed by &lt;span class='notranslate'&gt;&lt;a href='http://www.snia.org'&gt;SNIA&lt;/a&gt; (Storage Networking Industry Association&lt;/span&gt; and have developed a first prototype of a &lt;span class='notranslate'&gt;VIM (Vendor Interface Module)&lt;/span&gt; for the &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://en.wikipedia.org/wiki/Ext4'&gt;ext4&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; file system based on adding another &lt;span class='notranslate'&gt;&lt;i&gt;namespace&lt;/i&gt;&lt;/span&gt; to the current &lt;a href='http://en.wikipedia.org/wiki/Extended_file_attributes'&gt;extended file attributes&lt;/a&gt; support.&amp;nbsp; Since other Linux developers might be interested in how to add an &lt;span class='notranslate'&gt;extended attributes namespace&lt;/span&gt; to a file system, I decided to publish this post as a guide.&lt;br /&gt;&lt;br /&gt;Extended file attributes (EA) are extensions to the normal attributes which are associated with &lt;span class='notranslate'&gt;&lt;i&gt;inodes&lt;/i&gt;&lt;/span&gt; in a file system.&amp;nbsp; They are simply &lt;span class='notranslate'&gt;&lt;i&gt;name:value&lt;/i&gt;&lt;/span&gt; pairs associated with files and directories and whose purpose is to provide additional functionality which is either defined by the operating system or a user application.&amp;nbsp; An EA may be defined or undefined.&amp;nbsp; If an EA is defined, its value may be empty or non-empty.&amp;nbsp; Most of the initial work to support EAs in Linux was done by &lt;span class='notranslate'&gt;Andreas Gruenbacher&lt;/span&gt; in the 2001 to 2004 timeframe and is based on work done in the &lt;span class='notranslate'&gt;SGI &lt;a href='http://en.wikipedia.org/wiki/XFS'&gt;XFS&lt;/a&gt;&lt;/span&gt; file system.&lt;br /&gt;&lt;br /&gt;EAs are stored directly in &lt;span class='notranslate'&gt;&lt;i&gt;inodes&lt;/i&gt;&lt;/span&gt; and on additional disk blocks if necessary.&amp;nbsp; Currently all EAs associated with a file must fit in an inode and one additional block.&amp;nbsp; Blocks that contain the identical set of EAs may be shared among several inodes.&amp;nbsp; EAs in inodes and on blocks have a different header followed by multiple entry descriptors.&amp;nbsp; Entry descriptors are sorted in disk blocks but are left unsorted in inodes.  &lt;br /&gt;&lt;br /&gt;EA names are zero-terminated strings and are always specified using a fully qualified &lt;span class='notranslate'&gt;&lt;i&gt;namespace.attribute&lt;/i&gt;&lt;/span&gt; e.g. &lt;span class='notranslate'&gt;&lt;i&gt;system.posix_acl_access&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;security.selinux&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; &lt;span class='notranslate'&gt;Namespaces&lt;/span&gt; are used to define different classes of EAs.&amp;nbsp; Different EA classes are required because the permissions and capabilities required  for manipulating EAs in one namespace may differ from one to another.&amp;nbsp; Currently Linux supports EA namespaces for &lt;span class='notranslate'&gt;SELinux (&lt;i&gt;security.&lt;/i&gt;)&lt;/span&gt;, system (&lt;i&gt;system.&lt;/i&gt;), trusted (&lt;i&gt;trusted.&lt;/i&gt;) and user (&lt;i&gt;user.&lt;/i&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span class='notranslate'&gt;Fedora 11&lt;/span&gt; comes with EA support in the &lt;span class='notranslate'&gt;Linux&lt;/span&gt; kernel and hence it is the kernel which must be modified in order to add another EA namespace.&amp;nbsp; In my case I wanted to add an EA namespace called &lt;span class='notranslate'&gt;&lt;i&gt;snia&lt;/i&gt;&lt;/span&gt; in order to support &lt;span class='notranslate'&gt;XAM XSet&lt;/span&gt; metadata (see below).  &lt;br /&gt;&lt;br /&gt;Here is the patch file for the &lt;span class='notranslate'&gt;Fedora 11&lt;/span&gt; &lt;span class='notranslate'&gt;&lt;i&gt;2.6.29.4-167.fc11&lt;/i&gt;&lt;/span&gt; kernel which implements the &lt;span class='notranslate'&gt;&lt;i&gt;snia&lt;/i&gt;&lt;/span&gt; namespace.&amp;nbsp; It should work for both &lt;span class='notranslate'&gt;32-bit&lt;/span&gt; and &lt;span class='notranslate'&gt;64-bit&lt;/span&gt; kernels but I have only tested it on a &lt;span class='notranslate'&gt;64-bit&lt;/span&gt; kernel.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;diff -uNrp kernel-2.6.29.orig/fs/ext4/Makefile kernel-2.6.29.new/fs/ext4/Makefile&lt;br /&gt;--- kernel-2.6.29.orig/fs/ext4/Makefile 2009-06-14 22:07:12.191464615 -0400&lt;br /&gt;+++ kernel-2.6.29.new/fs/ext4/Makefile  2009-06-14 22:06:20.009399924 -0400&lt;br /&gt;@@ -8,6 +8,6 @@ ext4-y  := balloc.o bitmap.o dir.o file.o&lt;br /&gt;                   ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \&lt;br /&gt;                   ext4_jbd2.o migrate.o mballoc.o&lt;br /&gt;&lt;br /&gt;-ext4-$(CONFIG_EXT4_FS_XATTR)           += xattr.o xattr_user.o xattr_trusted.o&lt;br /&gt;+ext4-$(CONFIG_EXT4_FS_XATTR)           += xattr.o xattr_user.o xattr_trusted.o xattr_snia.o&lt;br /&gt; ext4-$(CONFIG_EXT4_FS_POSIX_ACL)       += acl.o&lt;br /&gt; ext4-$(CONFIG_EXT4_FS_SECURITY)                += xattr_security.o&lt;br /&gt;diff -uNrp kernel-2.6.29.orig/fs/ext4/xattr.c kernel-2.6.29.new/fs/ext4/xattr.c&lt;br /&gt;--- kernel-2.6.29.orig/fs/ext4/xattr.c  2009-06-14 22:11:20.699475221 -0400&lt;br /&gt;+++ kernel-2.6.29.new/fs/ext4/xattr.c   2009-06-14 22:09:48.242839367 -0400&lt;br /&gt;@@ -107,6 +107,7 @@ static struct xattr_handler *ext4_xattr_&lt;br /&gt; #ifdef CONFIG_EXT4_FS_SECURITY&lt;br /&gt;        [EXT4_XATTR_INDEX_SECURITY]          = &amp;ext4_xattr_security_handler,&lt;br /&gt; #endif&lt;br /&gt;+       [EXT4_XATTR_INDEX_SNIA]              = &amp;ext4_xattr_snia_handler,&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; struct xattr_handler *ext4_xattr_handlers[] = {&lt;br /&gt;@@ -119,6 +120,7 @@ struct xattr_handler *ext4_xattr_handler&lt;br /&gt; #ifdef CONFIG_EXT4_FS_SECURITY&lt;br /&gt;        &amp;ext4_xattr_security_handler,&lt;br /&gt; #endif&lt;br /&gt;+       &amp;ext4_xattr_snia_handler,&lt;br /&gt;        NULL&lt;br /&gt; };&lt;br /&gt;diff -uNrp kernel-2.6.29.orig/fs/ext4/xattr.h kernel-2.6.29.new/fs/ext4/xattr.h&lt;br /&gt;--- kernel-2.6.29.orig/fs/ext4/xattr.h  2009-06-14 22:09:27.016464602 -0400&lt;br /&gt;+++ kernel-2.6.29.new/fs/ext4/xattr.h   2009-06-14 22:07:44.887839381 -0400&lt;br /&gt;@@ -21,6 +21,7 @@&lt;br /&gt; #define EXT4_XATTR_INDEX_TRUSTED               4&lt;br /&gt; #define        EXT4_XATTR_INDEX_LUSTRE                 5&lt;br /&gt; #define EXT4_XATTR_INDEX_SECURITY              6&lt;br /&gt;+#define EXT4_XATTR_INDEX_SNIA                  7&lt;br /&gt;&lt;br /&gt; struct ext4_xattr_header {&lt;br /&gt;        __le32  h_magic;        /* magic number for identification */&lt;br /&gt;@@ -70,6 +71,7 @@ extern struct xattr_handler ext4_xattr_t&lt;br /&gt; extern struct xattr_handler ext4_xattr_acl_access_handler;&lt;br /&gt; extern struct xattr_handler ext4_xattr_acl_default_handler;&lt;br /&gt; extern struct xattr_handler ext4_xattr_security_handler;&lt;br /&gt;+extern struct xattr_handler ext4_xattr_snia_handler;&lt;br /&gt;&lt;br /&gt; extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);&lt;br /&gt;diff -uNrp kernel-2.6.29.orig/fs/ext4/xattr_snia.c kernel-2.6.29.new/fs/ext4/xattr_snia.c&lt;br /&gt;--- kernel-2.6.29.orig/fs/ext4/xattr_snia.c     1969-12-31 19:00:00.000000000 -0500&lt;br /&gt;+++ kernel-2.6.29.new/fs/ext4/xattr_snia.c      2009-06-14 13:37:02.551476954 -0400&lt;br /&gt;@@ -0,0 +1,68 @@&lt;br /&gt;+/*&lt;br /&gt;+ * linux/fs/ext4/xattr_snia.c&lt;br /&gt;+ * Handler for extended user attributes.&lt;br /&gt;+ *&lt;br /&gt;+ * Copyright (C) 2001 by Andreas Gruenbacher, &lt;a.gruenbacher@computer.org&gt;&lt;br /&gt;+ * Copyright (C) 2009 by Finnbarr P. Murphy, &lt;f.murphy@computer.org&gt;&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+#include &lt;linux/module.h&gt;&lt;br /&gt;+#include &lt;linux/string.h&gt;&lt;br /&gt;+#include &lt;linux/fs.h&gt;&lt;br /&gt;+#include "ext4_jbd2.h"&lt;br /&gt;+#include "ext4.h"&lt;br /&gt;+#include "xattr.h"&lt;br /&gt;+&lt;br /&gt;+static size_t&lt;br /&gt;+ext4_xattr_snia_list(struct inode *inode, char *list, size_t list_size,&lt;br /&gt;+                    const char *name, size_t name_len)&lt;br /&gt;+{&lt;br /&gt;+       const size_t prefix_len = XATTR_SNIA_PREFIX_LEN;&lt;br /&gt;+       const size_t total_len = prefix_len + name_len + 1;&lt;br /&gt;+&lt;br /&gt;+#if FPM&lt;br /&gt;+       if (!test_opt(inode-&gt;i_sb, XATTR_USER))&lt;br /&gt;+               return 0;&lt;br /&gt;+#endif&lt;br /&gt;+&lt;br /&gt;+       if (list &amp;&amp; total_len &lt;= list_size) {&lt;br /&gt;+               memcpy(list, XATTR_SNIA_PREFIX, prefix_len);&lt;br /&gt;+               memcpy(list+prefix_len, name, name_len);&lt;br /&gt;+               list[prefix_len + name_len] = '\0';&lt;br /&gt;+       }&lt;br /&gt;+       return total_len;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+static int&lt;br /&gt;+ext4_xattr_snia_get(struct inode *inode, const char *name,&lt;br /&gt;+                   void *buffer, size_t size)&lt;br /&gt;+{&lt;br /&gt;+       if (strcmp(name, "") == 0)&lt;br /&gt;+               return -EINVAL;&lt;br /&gt;+#if FPM&lt;br /&gt;+       if (!test_opt(inode-&gt;i_sb, XATTR_USER))&lt;br /&gt;+               return -EOPNOTSUPP;&lt;br /&gt;+#endif&lt;br /&gt;+       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SNIA, name, buffer, size);&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+static int&lt;br /&gt;+ext4_xattr_snia_set(struct inode *inode, const char *name,&lt;br /&gt;+                   const void *value, size_t size, int flags)&lt;br /&gt;+{&lt;br /&gt;+       if (strcmp(name, "") == 0)&lt;br /&gt;+               return -EINVAL;&lt;br /&gt;+#if FPM&lt;br /&gt;+       if (!test_opt(inode-&gt;i_sb, XATTR_USER))&lt;br /&gt;+               return -EOPNOTSUPP;&lt;br /&gt;+#endif&lt;br /&gt;+       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SNIA, name,&lt;br /&gt;+                             value, size, flags);&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+struct xattr_handler ext4_xattr_snia_handler = {&lt;br /&gt;+       .prefix = XATTR_SNIA_PREFIX,&lt;br /&gt;+       .list   = ext4_xattr_snia_list,&lt;br /&gt;+       .get    = ext4_xattr_snia_get,&lt;br /&gt;+       .set    = ext4_xattr_snia_set,&lt;br /&gt;+};&lt;br /&gt;diff -uNrp kernel-2.6.29.orig/fs/xattr.c kernel-2.6.29.new/fs/xattr.c&lt;br /&gt;--- kernel-2.6.29.orig/fs/xattr.c       2009-06-14 22:04:37.472464234 -0400&lt;br /&gt;+++ kernel-2.6.29.new/fs/xattr.c        2009-06-14 22:05:56.759530990 -0400&lt;br /&gt;@@ -42,6 +42,7 @@ xattr_permission(struct inode *inode, co&lt;br /&gt;         * on these is left to the underlying filesystem / security module.&lt;br /&gt;         */&lt;br /&gt;        if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||&lt;br /&gt;+           !strncmp(name, XATTR_SNIA_PREFIX, XATTR_SNIA_PREFIX_LEN) ||&lt;br /&gt;            !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))&lt;br /&gt;                return 0;&lt;br /&gt;&lt;br /&gt;diff -uNrp kernel-2.6.29.orig/include/linux/xattr.h kernel-2.6.29.new/include/linux/xattr.h&lt;br /&gt;--- kernel-2.6.29.orig/include/linux/xattr.h    2009-06-14 14:53:02.350464255 -0400&lt;br /&gt;+++ kernel-2.6.29.new/include/linux/xattr.h     2009-06-14 14:51:07.585839446 -0400&lt;br /&gt;@@ -33,6 +33,9 @@&lt;br /&gt; #define XATTR_USER_PREFIX "user."&lt;br /&gt; #define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)&lt;br /&gt;&lt;br /&gt;+#define XATTR_SNIA_PREFIX "snia."&lt;br /&gt;+#define XATTR_SNIA_PREFIX_LEN (sizeof (XATTR_SNIA_PREFIX) - 1)&lt;br /&gt;+&lt;br /&gt; struct inode;&lt;br /&gt; struct dentry;&lt;/pre&gt;&lt;/div&gt;I am going to assume that if you are still reading this post you know how to build, package and install a &lt;span class='notranslate'&gt;Linux&lt;/span&gt; kernel in &lt;/span class='notranslate'&gt;Fedora&lt;/span&gt;.&amp;nbsp; If not, here is a good &lt;a href='http://fedoraproject.org/wiki/Docs/CustomKernel#Prepare_Build_Files'&gt;tutorial&lt;/a&gt;.&amp;nbsp; The only caveat I would make is to ignore the comment that "most text editors know how to break the hardlink correctly to avoid problems."&amp;nbsp; That is just plain wrong.&amp;nbsp; You need to have separate standalone copies of any source file that you intend modifying in both the original and new kernel source trees - not a single hard linked copy - before you start making changes in the new kernel source tree.    &lt;br /&gt;&lt;br /&gt;Once you are running on the new kernel, you can set and get EAs in the &lt;span class='notranslate'&gt;&lt;i&gt;snia&lt;/i&gt;&lt;/span&gt; namespace as shown in this simple example.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ touch testfile&lt;br /&gt;$ setfattr -n snia.test -v "hello world" testfile&lt;br /&gt;$ getfattr -n snia.test testfile&lt;br /&gt;# file: testfile&lt;br /&gt;snia.test="hello world"&lt;br /&gt;&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;In the next example I set and get the metadata (called &lt;span class='notranslate'&gt;&lt;i&gt;fields&lt;/i&gt;&lt;/span&gt; in &lt;span class='notranslate'&gt;XAM&lt;/span&gt; terminology) for a sample &lt;span class='notranslate'&gt;XAM XSet&lt;/span&gt;.&amp;nbsp; A &lt;span class='notranslate'&gt;&lt;i&gt;field&lt;/i&gt;&lt;span&gt; has a name and a value, and the following standard attributes: &lt;span class='notranslate'&gt;&lt;i&gt;type&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;length&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;binding&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;readonly&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; The attributes and values roughly correspond to the &lt;span class='notranslate'&gt;&lt;i&gt;fields&lt;/i&gt;&lt;span&gt; outputted as an XML document to a persisted &lt;span class='notranslate'&gt;XSet&lt;/span&gt; by the &lt;span class="notranslate"&gt;&lt;i&gt;ReferenceXSetClient&lt;/i&gt;&lt;/span&gt; example included with the &lt;span class='notranslate'&gt;XAM SDK&lt;/span&gt; which is available on the &lt;span class='notranslate'&gt;SNIA&lt;/span&gt; website.&amp;nbsp; For an introduction to the concepts of an &lt;span class='notranslate'&gt;XSystem&lt;/span&gt; and &lt;span class='notranslate'&gt;XSets&lt;/span&gt; a good starting place is &lt;span class='notranslate'&gt;&lt;a href='http://blogs.sun.com/mac/entry/xam_java_binding_overview'&gt;Mark Carlson&lt;/a&gt;&lt;/span&gt;'s blog.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ cat xamtest&lt;br /&gt;# file: testfile&lt;br /&gt;snia.xset.hold.type="application/vnd.snia.xam.boolean"&lt;br /&gt;snia.xset.hold.binding="false"&lt;br /&gt;snia.xset.hold.readOnly="true"&lt;br /&gt;snia.xset.hold.length="1"&lt;br /&gt;snia.xset.hold="0"&lt;br /&gt;snia.xset.management.policy.type="application/vnd.snia.xam.string"&lt;br /&gt;snia.xset.management.policy.binding="true"&lt;br /&gt;snia.xset.management.policy.readOnly="true"&lt;br /&gt;snia.xset.management.policy.length="36"&lt;br /&gt;snia.xset.management.policy="org.snia.refvim.default.mgmt.policy"&lt;br /&gt;snia.xset.retention.base.enabled.type="application/vnd.snia.xam.boolean"&lt;br /&gt;snia.xset.retention.base.enabled.binding="true"&lt;br /&gt;snia.xset.retention.base.enabled.readOnly="true"&lt;br /&gt;snia.xset.retention.base.enabled.length="1"&lt;br /&gt;snia.xset.retention.base="1"&lt;br /&gt;snia.xset.retention.base.starttime.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.retention.base.starttime.binding="true"&lt;br /&gt;snia.xset.retention.base.starttime.readOnly="true"&lt;br /&gt;snia.xset.retention.base.starttime.length="29"&lt;br /&gt;snia.xset.retention.base.starttime="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.retention.list.base.type="application/vnd.snia.xam.string"&lt;br /&gt;snia.xset.retention.list.base.binding="true"&lt;br /&gt;snia.xset.retention.list.base.readOnly="true"&lt;br /&gt;snia.xset.retention.list.base.length="4"&lt;br /&gt;snia.xset.retention.list.base="base"&lt;br /&gt;snia.xset.retention.list.event.type="application/vnd.snia.xam.string"&lt;br /&gt;snia.xset.retention.list.event.binding="true"&lt;br /&gt;snia.xset.retention.list.event.readOnly="true"&lt;br /&gt;snia.xset.retention.list.event.length="5"&lt;br /&gt;snia.xset.retention.list.event="event"&lt;br /&gt;snia.xset.time.access.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.access.binding="false"&lt;br /&gt;snia.xset.time.access.readOnly="true"&lt;br /&gt;snia.xset.time.access.length="29"&lt;br /&gt;snia.xset.time.access="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.time.commit.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.commit.binding="false"&lt;br /&gt;snia.xset.time.commit.readOnly="true"&lt;br /&gt;snia.xset.time.commit.length="29"&lt;br /&gt;snia.xset.time.commit="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.time.access.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.access.binding="false"&lt;br /&gt;snia.xset.time.access.readOnly="true"&lt;br /&gt;snia.xset.time.access.length="29"&lt;br /&gt;snia.xset.time.access="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.time.commit.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.commit.binding="false"&lt;br /&gt;snia.xset.time.commit.readOnly="true"&lt;br /&gt;snia.xset.time.commit.length="29"&lt;br /&gt;snia.xset.time.commit="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.time.creation.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.creation.binding="true"&lt;br /&gt;snia.xset.time.creation.readOnly="true"&lt;br /&gt;snia.xset.time.creation.length="29"&lt;br /&gt;snia.xset.time.creation="2009-06-12T22:34:35.331-05:00"&lt;br /&gt;snia.xset.time.xuid.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.xuid.binding="false"&lt;br /&gt;snia.xset.time.xuid.readOnly="true"&lt;br /&gt;snia.xset.time.xuid.length="29"&lt;br /&gt;snia.xset.time.xuid="2009-06-12T22:34:35.331-05:00"&lt;br /&gt;snia.xset.xuid.type="application/vnd.snia.xam.xuid"&lt;br /&gt;snia.xset.xuid.binding="true"&lt;br /&gt;snia.xset.xuid.readOnly="true"&lt;br /&gt;snia.xset.xuid.length="30"&lt;br /&gt;snia.xset.xuid="AAA6AwAeVG4xMjQ0ODY0MDc1MzU4AQWDedILNL7Q"&lt;br /&gt;&lt;br /&gt;$ setfattr --restore=xamtest&lt;br /&gt;&lt;br /&gt;$ getfattr -m snia. -d testfile&lt;br /&gt;# file: testfile&lt;br /&gt;snia.test="hello world"&lt;br /&gt;snia.xset.hold="0"&lt;br /&gt;snia.xset.hold.binding="false"&lt;br /&gt;snia.xset.hold.length="1"&lt;br /&gt;snia.xset.hold.readOnly="true"&lt;br /&gt;snia.xset.hold.type="\"application/vnd.snia.xam.boolean\" "&lt;br /&gt;snia.xset.management.policy="org.snia.refvim.default.mgmt.policy"&lt;br /&gt;snia.xset.management.policy.binding="true"&lt;br /&gt;snia.xset.management.policy.length="36"&lt;br /&gt;snia.xset.management.policy.readOnly="true"&lt;br /&gt;snia.xset.management.policy.type="application/vnd.snia.xam.string"&lt;br /&gt;snia.xset.retention.base="1"&lt;br /&gt;snia.xset.retention.base.enabled.binding="\"true\" "&lt;br /&gt;snia.xset.retention.base.enabled.length="1"&lt;br /&gt;snia.xset.retention.base.enabled.readOnly="true"&lt;br /&gt;snia.xset.retention.base.enabled.type="application/vnd.snia.xam.boolean"&lt;br /&gt;snia.xset.retention.base.starttime="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.retention.base.starttime.binding="true"&lt;br /&gt;snia.xset.retention.base.starttime.length="29"&lt;br /&gt;snia.xset.retention.base.starttime.readOnly="true"&lt;br /&gt;snia.xset.retention.base.starttime.type="\"application/vnd.snia.xam.datetime\" "&lt;br /&gt;snia.xset.retention.list.base="base"&lt;br /&gt;snia.xset.retention.list.base.binding="true"&lt;br /&gt;snia.xset.retention.list.base.length="4"&lt;br /&gt;snia.xset.retention.list.base.readOnly="true"&lt;br /&gt;snia.xset.retention.list.base.type="application/vnd.snia.xam.string"&lt;br /&gt;snia.xset.retention.list.event="event"&lt;br /&gt;snia.xset.retention.list.event.binding="true"&lt;br /&gt;snia.xset.retention.list.event.length="5"&lt;br /&gt;snia.xset.retention.list.event.readOnly="true"&lt;br /&gt;snia.xset.retention.list.event.type="application/vnd.snia.xam.string"&lt;br /&gt;snia.xset.time.access="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.time.access.binding="false"&lt;br /&gt;snia.xset.time.access.length="29"&lt;br /&gt;snia.xset.time.access.readOnly="true"&lt;br /&gt;snia.xset.time.access.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.commit="2009-06-12T22:34:35.350-05:00"&lt;br /&gt;snia.xset.time.commit.binding="false"&lt;br /&gt;snia.xset.time.commit.length="29"&lt;br /&gt;snia.xset.time.commit.readOnly="true"&lt;br /&gt;snia.xset.time.commit.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.creation="2009-06-12T22:34:35.331-05:00"&lt;br /&gt;snia.xset.time.creation.binding="true"&lt;br /&gt;snia.xset.time.creation.length="29"&lt;br /&gt;snia.xset.time.creation.readOnly="true"&lt;br /&gt;snia.xset.time.creation.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.time.xuid="2009-06-12T22:34:35.331-05:00"&lt;br /&gt;snia.xset.time.xuid.binding="false"&lt;br /&gt;snia.xset.time.xuid.length="29"&lt;br /&gt;snia.xset.time.xuid.readOnly="true"&lt;br /&gt;snia.xset.time.xuid.type="application/vnd.snia.xam.datetime"&lt;br /&gt;snia.xset.xuid="AAA6AwAeVG4xMjQ0ODY0MDc1MzU4AQWDedILNL7Q"&lt;br /&gt;snia.xset.xuid.binding="true"&lt;br /&gt;snia.xset.xuid.length="30"&lt;br /&gt;snia.xset.xuid.readOnly="true"&lt;br /&gt;snia.xset.xuid.type="application/vnd.snia.xam.xuid"&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;Obviously this work is a proof-of-concept only.&amp;nbsp; The actual &lt;span class='notranslate'&gt;XAM&lt;/span&gt; namespace is &lt;span class='notranslate'&gt;&lt;i&gt;org.snia.xam.*&lt;/i&gt;&lt;/span&gt; and not the shortened version, i.e. &lt;span class='notranslate'&gt;&lt;i&gt;snia.*&lt;/i&gt;&lt;/span&gt;, which I used in the proof-of-concept.&amp;nbsp; I have not tested it sufficiently to discover boundary conditions or size limitations yet.&amp;nbsp; I suspect that it might be better to store the &lt;span class='notranslate'&gt;&lt;i&gt;snia&lt;/i&gt;&lt;/span&gt; namespace attributes in their own block(s) rather than sharing an inode or block with the other four namespaces and this is what I intend to prototype next.&lt;br /&gt;&lt;br /&gt;If anybody else is interested in working with me in this space I would welcome their involvement.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-2212036591124489889?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/2212036591124489889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/fedore-11-extended-attibutes-namespace.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/2212036591124489889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/2212036591124489889'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/fedore-11-extended-attibutes-namespace.html' title='Fedora 11 New Extended File Attributes Namespace'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-6226749326361086900</id><published>2009-06-11T13:07:00.040-04:00</published><updated>2009-06-12T13:07:19.236-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nouveau'/><category scheme='http://www.blogger.com/atom/ns#' term='NVIDIA'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='TwinView'/><category scheme='http://www.blogger.com/atom/ns#' term='MTTR'/><category scheme='http://www.blogger.com/atom/ns#' term='Fedora 11'/><title type='text'>Fedora 11 nVidia Twinview Support</title><content type='html'>&lt;span class='notranslate'&gt;Fedora 11 (&lt;i&gt;Leonidas&lt;/i&gt;)&lt;/span&gt; ships with the &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://nouveau.freedesktop.org/wiki/'&gt;nouveau&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; &lt;span class='notranslate'&gt;nVidia&lt;/span&gt; graphics driver preloaded by default if a &lt;span class='notranslate'&gt;nVidia&lt;/span&gt; graphics card is detected at install time.&amp;nbsp; Previous versions of &lt;span class='notranslate'&gt;Fedora&lt;/span&gt; used the older &lt;span class='notranslate'&gt;X.Org &lt;i&gt;&lt;a href='http://xorg.freedesktop.org/wiki/nv'&gt;nv&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; driver.&lt;br /&gt;&lt;br /&gt;The &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://nouveau.freedesktop.org/wiki/'&gt;nouveau&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; project aims at producing &lt;span class='notranslate'&gt;Open Source&lt;/span&gt; 3D drivers for nVidia graphics cards.&amp;nbsp; According to the &lt;span class='notranslate'&gt;nouveau&lt;/span&gt; project &lt;span class='notranslate'&gt;Wiki&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;2D-support is in fairly good shape with EXA acceleration, Xv and Randr12 (think of dual-head, rotations, etc.). Randr12 should work for all cards up to, and including, Geforce 9000 series, although some issues with Geforce 8/9 laptops may still exist, for such issues bug reports should be submitted. Randr12 is now the default. Any 3D functionality that might exist is still unsupported, do not ask for instructions to try it. Also, VT switching while X is running is considered lucky."&lt;/blockquote&gt; &lt;br /&gt;Well, I certainly quickly ran into the VT switching issue!&amp;nbsp; It worked but not consistently.&lt;br /&gt;&lt;br /&gt;Unfortunately the &lt;span class='notranslate'&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt; driver currently does not support &lt;span class='notranslate'&gt;nVidia &lt;a href='www.nvidia.com/object/feature_twinview.html'&gt;TwinView&lt;/a&gt;&lt;/span&gt; functionality and I suspect that it will be a long time before it does if ever! &lt;br /&gt;&lt;br /&gt;To use &lt;span class='notranslate'&gt;TwinView&lt;/span&gt; with &lt;span class='notranslate'&gt;Fedora 11&lt;/span&gt;, you have to load the correct &lt;span class='notranslate'&gt;nVidia&lt;/span&gt; drivers from &lt;span class='notranslate'&gt;&lt;a href='http://rpmfusion.org'&gt;rpmfusion.org&lt;/a&gt;&lt;/span&gt;.&amp;nbsp; I described how to do this in detail in a previous &lt;a href='http://fpmurphy.blogspot.com/2009/03/fedora-10-dual-head-graphics-card.html'&gt;post&lt;/a&gt; so I will not repeat that information here. &lt;br /&gt;&lt;br /&gt;You also need to modify your &lt;span class='notranslate'&gt;&lt;i&gt;grub.conf&lt;/i&gt;&lt;/span&gt; file to include the &lt;span class="notranslate"&gt;&lt;i&gt;nopat&lt;/i&gt;&lt;/span&gt; kernel boot option as shown below.&lt;div class="notranslate"&gt;&lt;pre class='displaybox'&gt;title Fedora (2.6.29.4-167.fc11.x86_64)&lt;br /&gt;       root (hd0,1)&lt;br /&gt;       kernel /vmlinuz-2.6.29.4-167.fc11.x86_64 ro root=/dev/mapper/vg_ultra-lv_root rhgb quiet nopat&lt;br /&gt;       initrd /initrd-2.6.29.4-167.fc11.x86_64.img&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;The &lt;span class="notranslate"&gt;&lt;i&gt;nopat&lt;/i&gt;&lt;/span&gt; option is needed for this particular kernel (2.6.29.4) as it appears to still have broken &lt;span class='notranslate'&gt;&lt;i&gt;PAT &lt;/i&gt;&lt;/span&gt; functionality. &lt;br /&gt;&lt;br /&gt;For those readers who are unaware of what &lt;span class="notranslate"&gt;&lt;i&gt;PAT&lt;/i&gt;&lt;/span&gt; is, here is a brief explanation.&amp;nbsp; Traditionally page caching was controlled by a &lt;span class="notranslate"&gt;CPU&lt;/span&gt; feature called &lt;span class="notranslate"&gt;&lt;i&gt;&lt;a href='http://en.wikipedia.org/wiki/Memory_Type_Range_Registers'&gt;Memory Type Range Registers&lt;/a&gt; (MTRR)&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; A &lt;span class="notranslate"&gt;CPU&lt;/span&gt; has a finite and limited set of &lt;span class="notranslate"&gt;&lt;i&gt;MTRR&lt;/i&gt;&lt;/span&gt;s each of which control part of the physical address space.&amp;nbsp; To overcome this limitation and provide a more flexible architecture, Intel and other x86 CPU vendors added a set of bits to page table entries to control how a &lt;span class="notranslate"&gt;CPU&lt;/span&gt; does page caching.&amp;nbsp; These bits are called the &lt;span class="notranslate"&gt;&lt;i&gt;&lt;a href='http://en.wikipedia.org/wiki/Page_Attribute_Table'&gt;Page Attribute Table&lt;/a&gt; (PAT)&lt;/i&gt;&lt;/span&gt;.&amp;nbsp;  Incidentally, the 2.6.26 kernel was the first &lt;span class="notranslate"&gt;Linux&lt;/span&gt; kernel to support &lt;span class="notranslate"&gt;PATs&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Unless you rebuild your initial ramdisk (&lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://en.wikipedia.org/wiki/Initrd'&gt;initrd&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;), the &lt;span class='notranslate'&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt; driver will remain loaded in the kernel.&amp;nbsp; I prefer not to have the &lt;span class='notranslate'&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt; driver loaded in my kernel if I am not using it so I added &lt;span class='notranslate'&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt; to the list of blacklisted drivers in &lt;span class='notranslate'&gt;&lt;i&gt;/etc/modprobe.d/blacklist.conf&lt;/i&gt;&lt;/span&gt; and rebuild &lt;span class='notranslate'&gt;&lt;i&gt;initrd&lt;/i&gt;&lt;/span&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;# mv /boot/initrd-`uname -r`.img /boot/initrd-`uname -r`.img.backup&lt;br /&gt;# mkinitrd -v /boot/initrd-`uname -r`.img `uname -r`&lt;br /&gt;Creating initramfs&lt;br /&gt;Looking for driver for /dev/mapper/vg_ultra-lv_root in /sys/block/dm-0&lt;br /&gt;Found DeviceMapper component dm-0&lt;br /&gt;Looking for deps of module scsi:t-0x00&lt;br /&gt;Looking for deps of module pci:v00008086d00002922sv00008086sd00005442bc01sc06i01&lt;br /&gt;Looking for driver for /dev/mapper/vg_ultra-lv_swap in /sys/block/dm-1&lt;br /&gt;Found DeviceMapper component dm-1&lt;br /&gt;Using modules:&lt;br /&gt;Building initrd in /tmp/initrd.txR0Kd&lt;br /&gt;/sbin/nash -&gt; /tmp/initrd.txR0Kd/bin/nash&lt;br /&gt;  /usr/lib64/libnash.so.6.0.86 -&gt; /tmp/initrd.txR0Kd/usr/lib64/libnash.so.6.0.86&lt;br /&gt;  /usr/lib64/libbdevid.so.6.0.86 -&gt; /tmp/initrd.txR0Kd/usr/lib64/libbdevid.so.6.0.86&lt;br /&gt;  /lib64/libdevmapper.so.1.02 -&gt; /tmp/initrd.txR0Kd/lib64/libdevmapper.so.1.02&lt;br /&gt;  /lib64/libparted-1.8.so.8 -&gt; /tmp/initrd.txR0Kd/lib64/libparted-1.8.so.8&lt;br /&gt;    /lib64//libparted-1.8.so.8.0.0 -&gt; /tmp/initrd.txR0Kd/lib64//libparted-1.8.so.8.0.0&lt;br /&gt;  /lib64/libblkid.so.1 -&gt; /tmp/initrd.txR0Kd/lib64/libblkid.so.1&lt;br /&gt;    /lib64//libblkid.so.1.0 -&gt; /tmp/initrd.txR0Kd/lib64//libblkid.so.1.0&lt;br /&gt;  /lib64/libselinux.so.1 -&gt; /tmp/initrd.txR0Kd/lib64/libselinux.so.1&lt;br /&gt;  /lib64/libsepol.so.1 -&gt; /tmp/initrd.txR0Kd/lib64/libsepol.so.1&lt;br /&gt;  /lib64/libuuid.so.1 -&gt; /tmp/initrd.txR0Kd/lib64/libuuid.so.1&lt;br /&gt;    /lib64//libuuid.so.1.2 -&gt; /tmp/initrd.txR0Kd/lib64//libuuid.so.1.2&lt;br /&gt;  /lib64/libpopt.so.0 -&gt; /tmp/initrd.txR0Kd/lib64/libpopt.so.0&lt;br /&gt;    /lib64//libpopt.so.0.0.0 -&gt; /tmp/initrd.txR0Kd/lib64//libpopt.so.0.0.0&lt;br /&gt;  /lib64/libresolv.so.2 -&gt; /tmp/initrd.txR0Kd/lib64/libresolv.so.2&lt;br /&gt;    /lib64//libresolv-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//libresolv-2.10.1.so&lt;br /&gt;      /lib64/libc.so.6 -&gt; /tmp/initrd.txR0Kd/lib64/libc.so.6&lt;br /&gt;        /lib64//libc-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//libc-2.10.1.so&lt;br /&gt;          /lib64/ld-linux-x86-64.so.2 -&gt; /tmp/initrd.txR0Kd/lib64/ld-linux-x86-64.so.2&lt;br /&gt;           /lib64//ld-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//ld-2.10.1.so&lt;br /&gt;  /lib64/libdl.so.2 -&gt; /tmp/initrd.txR0Kd/lib64/libdl.so.2&lt;br /&gt;    /lib64//libdl-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//libdl-2.10.1.so&lt;br /&gt;  /usr/lib64/libelf.so.1 -&gt; /tmp/initrd.txR0Kd/usr/lib64/libelf.so.1&lt;br /&gt;    /usr/lib64//libelf-0.141.so -&gt; /tmp/initrd.txR0Kd/usr/lib64//libelf-0.141.so&lt;br /&gt;  /usr/lib64/libnl.so.1 -&gt; /tmp/initrd.txR0Kd/usr/lib64/libnl.so.1&lt;br /&gt;    /usr/lib64//libnl.so.1.1 -&gt; /tmp/initrd.txR0Kd/usr/lib64//libnl.so.1.1&lt;br /&gt;  /lib64/libm.so.6 -&gt; /tmp/initrd.txR0Kd/lib64/libm.so.6&lt;br /&gt;    /lib64//libm-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//libm-2.10.1.so&lt;br /&gt;  /lib64/libgcc_s.so.1 -&gt; /tmp/initrd.txR0Kd/lib64/libgcc_s.so.1&lt;br /&gt;    /lib64//libgcc_s-4.4.0-20090506.so.1 -&gt; /tmp/initrd.txR0Kd/lib64//libgcc_s-4.4.0-20090506.so.1&lt;br /&gt;  /lib64/libreadline.so.5 -&gt; /tmp/initrd.txR0Kd/lib64/libreadline.so.5&lt;br /&gt;    /lib64//libreadline.so.5.2 -&gt; /tmp/initrd.txR0Kd/lib64//libreadline.so.5.2&lt;br /&gt;  /lib64/librt.so.1 -&gt; /tmp/initrd.txR0Kd/lib64/librt.so.1&lt;br /&gt;    /lib64//librt-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//librt-2.10.1.so&lt;br /&gt;      /lib64/libpthread.so.0 -&gt; /tmp/initrd.txR0Kd/lib64/libpthread.so.0&lt;br /&gt;        /lib64//libpthread-2.10.1.so -&gt; /tmp/initrd.txR0Kd/lib64//libpthread-2.10.1.so&lt;br /&gt;  /lib64/libtinfo.so.5 -&gt; /tmp/initrd.txR0Kd/lib64/libtinfo.so.5&lt;br /&gt;    /lib64//libtinfo.so.5.7 -&gt; /tmp/initrd.txR0Kd/lib64//libtinfo.so.5.7&lt;br /&gt;/sbin/modprobe -&gt; /tmp/initrd.txR0Kd/bin/modprobe&lt;br /&gt;/sbin/rmmod -&gt; /tmp/initrd.txR0Kd/bin/rmmod&lt;br /&gt;resolving for MODULES&lt;br /&gt;and that has items of&lt;br /&gt;resolving for availmodules&lt;br /&gt;and that has items of&lt;br /&gt;/sbin/lvm -&gt; /tmp/initrd.txR0Kd/bin/lvm&lt;br /&gt;/etc/lvm -&gt; /tmp/initrd.txR0Kd/etc/lvm&lt;br /&gt;`/etc/lvm/lvm.conf' -&gt; `/tmp/initrd.txR0Kd/etc/lvm/lvm.conf'&lt;br /&gt;/etc/sysconfig/keyboard -&gt; /tmp/initrd.txR0Kd/etc/sysconfig/keyboard&lt;br /&gt;/bin/loadkeys -&gt; /tmp/initrd.txR0Kd/bin/loadkeys&lt;br /&gt;/lib/kbd/keymaps/i386/qwerty/us.map.gz -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/qwerty/us.map.gz&lt;br /&gt;/lib/kbd/keymaps/i386/include/qwerty-layout.inc -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/qwerty-layout.inc&lt;br /&gt;/lib/kbd/keymaps/i386/include/compose.inc -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/compose.inc&lt;br /&gt;/lib/kbd/keymaps/include/compose.latin4 -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin4&lt;br /&gt;/lib/kbd/keymaps/include/compose.8859_8 -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.8859_8&lt;br /&gt;/lib/kbd/keymaps/include/compose.latin1 -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin1&lt;br /&gt;/lib/kbd/keymaps/include/compose.latin3 -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin3&lt;br /&gt;/lib/kbd/keymaps/include/compose.8859_7 -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.8859_7&lt;br /&gt;/lib/kbd/keymaps/include/compose.latin2 -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin2&lt;br /&gt;/lib/kbd/keymaps/include/compose.latin -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin&lt;br /&gt;/lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc&lt;br /&gt;/lib/kbd/keymaps/i386/include/linux-keys-bare.inc -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/linux-keys-bare.inc&lt;br /&gt;/lib/kbd/keymaps/i386/include/euro1.map.gz -&gt; /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/euro1.map.gz&lt;br /&gt;/etc/sysconfig/i18n -&gt; /tmp/initrd.txR0Kd/etc/sysconfig/i18n&lt;br /&gt;/bin/setfont -&gt; /tmp/initrd.txR0Kd/bin/setfont&lt;br /&gt;/lib/kbd/consolefonts/latarcyrheb-sun16.psfu.gz -&gt; /tmp/initrd.txR0Kd/lib/kbd/consolefonts/latarcyrheb-sun16.psfu.gz&lt;br /&gt;/lib/udev/console_init -&gt; /tmp/initrd.txR0Kd/lib/udev/console_init&lt;br /&gt;  /lib64/libglib-2.0.so.0 -&gt; /tmp/initrd.txR0Kd/lib64/libglib-2.0.so.0&lt;br /&gt;    /lib64//libglib-2.0.so.0.2000.1 -&gt; /tmp/initrd.txR0Kd/lib64//libglib-2.0.so.0.2000.1&lt;br /&gt;probing for modules for drm device card0&lt;br /&gt;Adding graphics device card0&lt;br /&gt;Looking for deps of module pci:v000010DEd00000640sv00003842sd0000C959bc03sc00i00: i2c-core nvidia&lt;br /&gt;Adding module i2c-core&lt;br /&gt;Adding module nvidia&lt;br /&gt;resolving for GRAPHICSMODS&lt;br /&gt;and that has items of i2c-core nvidia&lt;br /&gt;Looking for deps of module i2c-core&lt;br /&gt;Looking for deps of module nvidia: i2c-core&lt;br /&gt;copy from `/lib/modules/2.6.29.4-167.fc11.x86_64/kernel/drivers/i2c/i2c-core.ko' [elf64-x86-64] to `/tmp/initrd.txR0Kd/lib/modules/2.6.29.4-167.fc11.x86_64/i2c-core.ko' [elf64-x86-64]&lt;br /&gt;copy from `/lib/modules/2.6.29.4-167.fc11.x86_64/extra/nvidia-173xx/nvidia.ko' [elf64-x86-64] to `/tmp/initrd.txR0Kd/lib/modules/2.6.29.4-167.fc11.x86_64/nvidia.ko' [elf64-x86-64]&lt;br /&gt;/sbin/plymouthd -&gt; /tmp/initrd.txR0Kd/bin/plymouthd&lt;br /&gt;........&lt;br /&gt;........&lt;br /&gt;Adding module scsi_wait_scan&lt;br /&gt;copy from `/lib/modules/2.6.29.4-167.fc11.x86_64/kernel/drivers/scsi/scsi_wait_scan.ko' [elf64-x86-64] to `/tmp/initrd.txR0Kd/lib/modules/2.6.29.4-167.fc11.x86_64/scsi_wait_scan.ko' [elf64-x86-64]&lt;br /&gt;This initrd uses dynamic shared objects.&lt;br /&gt;Adding dynamic linker configuration files.&lt;br /&gt;/etc/ld.so.conf -&gt; /tmp/initrd.txR0Kd/etc/ld.so.conf&lt;br /&gt;/etc/ld.so.conf.d/kernel-2.6.29.4-167.fc11.x86_64.conf -&gt; /tmp/initrd.txR0Kd/etc/ld.so.conf.d/kernel-2.6.29.4-167.fc11.x86_64.conf&lt;br /&gt;/etc/ld.so.conf.d/mysql-x86_64.conf -&gt; /tmp/initrd.txR0Kd/etc/ld.so.conf.d/mysql-x86_64.conf&lt;br /&gt;/etc/ld.so.conf.d/nvidia-lib64.conf -&gt; /tmp/initrd.txR0Kd/etc/ld.so.conf.d/nvidia-lib64.conf&lt;br /&gt;/etc/ld.so.conf.d/xulrunner-64.conf -&gt; /tmp/initrd.txR0Kd/etc/ld.so.conf.d/xulrunner-64.conf&lt;br /&gt;/etc/ld.so.conf.d/qt-x86_64.conf -&gt; /tmp/initrd.txR0Kd/etc/ld.so.conf.d/qt-x86_64.conf&lt;br /&gt;Running ldconfig&lt;br /&gt;#&lt;/pre&gt;&lt;/div&gt;After rebooting your system, if you use &lt;span class='notranslate'&gt;&lt;i&gt;dmesg&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;lsmod&lt;/i&gt;&lt;/span&gt;, you will see that the &lt;span class='notranslate'&gt;&lt;i&gt;nvidia&lt;/i&gt;&lt;/span&gt; driver was loaded instead of the &lt;span class='notranslate'&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt; driver.&lt;br /&gt;&lt;br /&gt;You will also see that for some reason &lt;span class='notranslate'&gt;&lt;a href='https://fedoraproject.org/wiki/Features/BetterStartup'&gt;Plymouth&lt;/a&gt;&lt;/span&gt; no longer runs with a graphical splash screen if it previously did so.&amp;nbsp; &lt;span class='notranslate'&gt;Plymouth is  the replacement for the old &lt;span class='notranslate'&gt;RedHat Graphical Boot (RHGB)&lt;/span&gt;.&amp;nbsp; It was written by Ray Strode, Kristian Hogsberg and Peter Jones of Redhat and first shipped in &lt;span class='notranslate'&gt;Fedora 10&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Finally, you do not need to modify your &lt;span class='notranslate'&gt;&lt;i&gt;xorg.conf&lt;/i&gt;&lt;/span&gt; file for &lt;span class='notranslate'&gt;Fedora 11&lt;/span&gt;.&amp;nbsp; It should just work. &lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-6226749326361086900?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/6226749326361086900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/fedora-11-nvidia-twinview-support.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/6226749326361086900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/6226749326361086900'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/06/fedora-11-nvidia-twinview-support.html' title='Fedora 11 nVidia Twinview Support'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-3477456496303422666</id><published>2009-05-28T11:14:00.082-04:00</published><updated>2009-06-12T12:36:57.064-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='POSIX.1e'/><category scheme='http://www.blogger.com/atom/ns#' term='linux capabilities'/><category scheme='http://www.blogger.com/atom/ns#' term='capset'/><category scheme='http://www.blogger.com/atom/ns#' term='capget'/><title type='text'>Linux Security Capabilities</title><content type='html'>In earlier times, the standard security model for &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; and &lt;span class='notranslate'&gt;Unix&lt;/span&gt; operating systems gave general users a minimal set of privileges, while granting full privileges to a single user account, i.e. root, that was used to administer the system and users, install software, mount and unmount filesystems, loading kernel modules, bind a process to a privileged port and run many services. &lt;br /&gt;&lt;br /&gt;This dependence upon the root account to perform all actions requiring privilege was recognized to be somewhat dangerous in that it was all or nothing and not suited to compartmentalization of roles.&amp;nbsp; Furthermore, it increased the risk of vulnerabilities within a setuid application which may only require root privileges for a very small fraction of its activity such as opening a system file or binding to a privileged port.&lt;br /&gt;&lt;br /&gt;This risk was well understood within the open systems community.&amp;nbsp; As a result, &lt;span class='notranslate'&gt;IEEE Std.1003.1e&lt;/span&gt; (aka &lt;span class='notranslate'&gt;POSIX.1e&lt;/span&gt; or &lt;/span class='notranslate'&gt;POSIX.6&lt;/span&gt;) was a major effect started in 1995 to develop a standardized set of security interfaces for conforming systems which included access control lists &lt;/span class='notranslate'&gt;(ACL)&lt;/span&gt;, audit, separation of privilege (&lt;span class='no translate'&gt;capabilities&lt;/span&gt;), mandatory access control &lt;span class='notranslate'&gt;(MAC)&lt;/span&gt; and information labels.&lt;br /&gt;&lt;br /&gt;The work was terminated by &lt;/span class='notranslate'&gt;IEEE's RevCon&lt;/span&gt; in 1998 at &lt;a href='http://www.fpmurphy.com/public/Posix_1003.1e-990310.pdf'&gt;draft 17&lt;/a&gt; of the document due to lack of consensus (mostly because of conflicting existing practice.)&amp;nbsp; While the formal standards effort failed, since then much of the draft standard has made its way in the &lt;span class='notranslate'&gt;Linux&lt;/span&gt; kernel including &lt;/span class='notranslate'&gt;capabilities&lt;/span&gt; which this post explores.&lt;br /&gt;&lt;br /&gt;First, what do we mean by Linux capabilities?&amp;nbsp; It is basically an extended verion of the capabilities model described in the draft &lt;span class='notranslate'&gt;POSIX.1e&lt;/span&gt; standard.&amp;nbsp; Readers familiar with &lt;span class='notranslate'&gt;&lt;a href='http://en.wikipedia.org/wiki/VMS'&gt;VMS&lt;/a&gt;&lt;/span&gt; or versions of Unix which include &lt;span class='notranslate'&gt;&lt;a href='http://en.wikipedia.org/wiki/Trusted_Computing_Base'&gt;Trusted Computing Base (TCB)&lt;/a&gt;&lt;/span&gt; will recognize it as being somewhat analogous to as &lt;span class='notranslate'&gt;&lt;i&gt;privileges&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; These capabilities partition the set of root privlileges into a set of distinct logical privileges which may be granted or assigned to processes, users, filesystems and more.&amp;nbsp; As an aside, the term &lt;span class='notranslate'&gt;&lt;i&gt;capability&lt;/i&gt;&lt;/span&gt; originated in a 1966 paper by &lt;span class='notranslate'&gt;Jack Dennis and &lt;/span 'notranslate'&gt;Earl Van Horn  (CACM vol 9, #3, pp 143-155, March 1966.)&lt;/span&gt;&amp;nbsp; Capabilities can be implemented in many ways including via hardware tags, cryptography, within a programming language (e.g.Java) or using protected address space.&amp;nbsp; For a introduction to capability-based mechanisms &lt;a href='http://www.cs.cornell.edu/Courses/cs513/2000sp/L08.html'&gt;go here&lt;/a&gt;.&amp;nbsp; &lt;span class='notranslate'&gt;Linux&lt;/span&gt; uses protected address space and &lt;span class='notranslate'&gt;extended file attributes&lt;/span&gt; to implement capabilities.&lt;br /&gt;&lt;br /&gt;A &lt;span class='notranslate'&gt;&lt;i&gt;capability flag&lt;/i&gt;&lt;/span&gt; is an attribute of a &lt;span class='notranslate'&gt;&lt;i&gt;capability&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; There are three &lt;span class='notranslate'&gt;&lt;i&gt;capability flags&lt;/i&gt;&lt;/span&gt;, named &lt;span class='notranslate'&gt;&lt;i&gt;permitted (p)&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;effective (e)&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;inherited (i)&lt;/i&gt;&lt;/span&gt;, associated with each of the &lt;span class='notranslate'&gt;&lt;i&gt;capabilities&lt;/i&gt;&lt;/span&gt; which, by the way, are documented in the &lt;span class='notranslate'&gt;&lt;i&gt;&amp;lt;security/capability.h&amp;gt;&lt;/i&gt;&lt;/span&gt; header.&lt;br /&gt;&lt;br /&gt;A &lt;span class='notranslate'&gt;&lt;i&gt;capability set&lt;/i&gt;&lt;/span&gt; consists of a 64-bit bitmap (prior to &lt;span class='notranslate'&gt;&lt;i&gt;libcap 2.03&lt;/i&gt;&lt;/span&gt; a bitmap was 32-bits.)&amp;nbsp; A process has a &lt;span class='notranslate'&gt;&lt;i&gt;capability state&lt;/i&gt;&lt;/span&gt; consisting of three capability sets, i.e. &lt;span class='notranslate'&gt;&lt;i&gt;inheritable (I)&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;permitted (P)&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;effective (E)&lt;/i&gt;&lt;/span&gt;, with each &lt;span class='notranslate'&gt;&lt;i&gt;capability flag&lt;/i&gt;&lt;/span&gt; implemented as a bit in each of the three bitmaps.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Whenever a process attempts a privileged operation, the kernel checks that the appropriate bit in the effective set is set.&amp;nbsp; For example, when a process tries to set the monotomic clock, the kernel first checks that the &lt;span class='notranslate'&gt;&lt;i&gt;CAP_SYS_TIME&lt;/i&gt;&lt;/span&gt; bit is set in the process effective set.&lt;br /&gt;&lt;br /&gt;The &lt;span class='notranslate'&gt;&lt;i&gt;permitted&lt;/i&gt;&lt;/span&gt; set indicates what capabilities a process can use.&amp;nbsp; A process can have capabilities set in the &lt;span class='notranslate'&gt;&lt;i&gt;permitted&lt;/i&gt;&lt;/span&gt; set that are not in the &lt;span class='notranslate'&gt;&lt;i&gt;effective&lt;/i&gt;&lt;/span&gt; set.&amp;nbsp; This indicates that the process has temporarily disabled this capability.&amp;nbsp; A process is allowed to set its &lt;span class='notranslate'&gt;effective&lt;/span&gt; set bit only if it is available in the &lt;span class='notranslate'&gt;&lt;i&gt;permitted&lt;/i&gt;&lt;/span&gt; set.&amp;nbsp; The distinction between &lt;span class='notranslate'&gt;&lt;i&gt;permitted&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;effective&lt;/i&gt;&lt;/span&gt; exists so that a process can bracket operations that need privilege.&lt;br /&gt;&lt;br /&gt;The &lt;span class='notranslate'&gt;&lt;i&gt;inheritable&lt;/i&gt;&lt;/span&gt; capabilities are the capabilities of the current process that should be inherited by a program executed by the current process.&amp;nbsp; The &lt;span class='notranslate'&gt;&lt;i&gt;permitted&lt;/i&gt;&lt;/span&gt; set of a process is masked against the &lt;span class='notranslate'&gt;&lt;i&gt;inheritable&lt;/i&gt;&lt;/span&gt; set during exec, while child processes and threads are given an exact copy of the capabilities of the parent process.&lt;br /&gt;&lt;br /&gt;Rather than going into a detailed explaination of &lt;span class='notranslate'&gt;&lt;i&gt;forced sets&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;capability&lt;/i&gt;&lt;/span&gt; calculations, I refer you to &lt;span class='notranslate'&gt;Chris Friedhoff's&lt;/span&gt; excellent &lt;span class='notranslate'&gt;&lt;a href='http://www.friedhoff.org/posixfilecaps.html'&gt; explanation&lt;/a&gt;&lt;/span&gt;.&amp;nbsp; However, I have summarized the rules in the following diagram. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_IrJjVkDo0pg/SiH4uljFaFI/AAAAAAAAAG8/AqQKT1sE7eI/s1600-h/Capture.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 430px; height: 240px;" src="http://3.bp.blogspot.com/_IrJjVkDo0pg/SiH4uljFaFI/AAAAAAAAAG8/AqQKT1sE7eI/s320/Capture.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5341824112275056722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For our first example of modifying capabilities consider the &lt;span class='notranslate'&gt;&lt;i&gt;ping&lt;/i&gt;&lt;/span&gt; utility.&amp;nbsp; Many people do not realise that it is a &lt;span class='notranslate'&gt;&lt;i&gt;setuid&lt;/i&gt;&lt;/span&gt; executable on most &lt;span class='notranslate'&gt;GNU/Linux systems&lt;/span&gt;.&amp;nbsp; It needs to be so because it needs privilege to write the type of packages it uses to probe the network.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ ls -al /bin/ping&lt;br /&gt;-rwsr-xr-x 1 root root 41784 2008-09-26 02:02 /bin/ping&lt;br /&gt;&lt;br /&gt;If you copy ping, it loses its setuid bit and fails to work&lt;br /&gt;&lt;br /&gt;$ cp /bin/ping .&lt;br /&gt;$ ls -al ping&lt;br /&gt;-rwxr-xr-x 1 fpm fpm 41784 2009-05-29 20:26 ping&lt;br /&gt;$ ./ping localhost&lt;br /&gt;ping: icmp open socket: Operation not permitted&lt;br /&gt;&lt;br /&gt;but works if you become root&lt;br /&gt;&lt;br /&gt;# ./ping -c1 localhost&lt;br /&gt;PING localhost.localdomain (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.026 ms&lt;br /&gt;&lt;br /&gt;--- localhost.localdomain ping statistics ---&lt;br /&gt;1 packets transmitted, 1 received, 0% packet loss, time 0ms&lt;br /&gt;rtt min/avg/max/mdev = 0.026/0.026/0.026/0.000 ms&lt;br /&gt;&lt;br /&gt;as root add CAP_NET_RAW to the permitted capability and set the legacy effective bit&lt;br /&gt;&lt;br /&gt;# /usr/sbin/setcap cap_net_raw=ep ./ping&lt;br /&gt;&lt;br /&gt;check what capabilities ping now has&lt;br /&gt;&lt;br /&gt;# /usr/sbin/getcap ./ping&lt;br /&gt;./ping = cap_net_raw+ep&lt;br /&gt;&lt;br /&gt;and this time ping works without being setuid&lt;br /&gt;&lt;br /&gt;$ ls -al ./ping&lt;br /&gt;-rwxr-xr-x 1 fpm fpm 41784 2009-05-29 20:26 ./ping&lt;br /&gt;$ ./ping -c1 localhost&lt;br /&gt;PING localhost.localdomain (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.026 ms&lt;br /&gt;&lt;br /&gt;--- localhost.localdomain ping statistics ---&lt;br /&gt;1 packets transmitted, 1 received, 0% packet loss, time 0ms&lt;br /&gt;rtt min/avg/max/mdev = 0.026/0.026/0.026/0.000 ms&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;Another scenario might be that we want to remove the &lt;span class='notranslate'&gt;&lt;i&gt;setuid&lt;/i&gt;&lt;/span&gt; bit from &lt;span class='notranslate'&gt;&lt;i&gt;ping&lt;/i&gt;&lt;/span&gt; but enable a non-root user to use it.&amp;nbsp; We can do this using the &lt;span class='notranslate'&gt;&lt;a href='http://en.wikipedia.org/wiki/Pluggable_Authentication_Modules'&gt;PAM&lt;/a&gt; &lt;i&gt;pam_cap&lt;/i&gt;&lt;/span&gt; module which is which is part of the &lt;span class='notranslate'&gt;&lt;i&gt;libcap &lt;/i&gt;&lt;/span&gt;package.&amp;nbsp; The default configuration file for this &lt;span class='notranslate'&gt;PAM&lt;/span&gt; module is &lt;span class='notranslate'&gt;&lt;i&gt;/etc/security/capability.conf&lt;/i&gt;&lt;/span&gt; but that can be overwritten using a &lt;span class='notranslate'&gt;&lt;i&gt;config=filename&lt;/i&gt;&lt;/span&gt; argument.&amp;nbsp; Another argument which you can pass to the module is &lt;span class='notranslate'&gt;&lt;i&gt;debug&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Any errors are written to the error log file for this module which is &lt;span class='notranslate'&gt;&lt;i&gt;pam_cap&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The following example shows how to configure &lt;span class='notranslate'&gt;&lt;i&gt;pam_cap&lt;/i&gt;&lt;/span&gt; to allow the user &lt;span class='notranslate'&gt;&lt;i&gt;test&lt;/i&gt;&lt;/span&gt; to use &lt;span class='notranslate'&gt;&lt;i&gt;ping&lt;/i&gt;&lt;/span&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;cat /security/capability.conf&lt;br /&gt;#&lt;br /&gt;# /etc/security/capability.conf&lt;br /&gt;# last edit FPM 05/29/2009&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;## user 'test' can use ping via inheritance&lt;br /&gt;cap_net_raw test&lt;br /&gt;&lt;br /&gt;## everyone else gets no inheritable capabilities&lt;br /&gt;none *&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;next insure that pam_cap.so is required by su&lt;br /&gt;&lt;br /&gt;cat /etc/pam.d/su&lt;br /&gt;#%PAM-1.0&lt;br /&gt;auth            sufficient      pam_rootok.so&lt;br /&gt;# Uncomment the following line to implicitly trust users in the "wheel" group.&lt;br /&gt;#auth           sufficient      pam_wheel.so trust use_uid&lt;br /&gt;# Uncomment the following line to require a user to be in the "wheel" group.&lt;br /&gt;#auth           required        pam_wheel.so use_uid&lt;br /&gt;# FPM added pam_cap.so  5/29/2009&lt;br /&gt;auth            required        pam_cap.so  debug&lt;br /&gt;auth            include         system-auth&lt;br /&gt;account         sufficient      pam_succeed_if.so uid = 0 use_uid quiet&lt;br /&gt;account         include         system-auth&lt;br /&gt;password        include         system-auth&lt;br /&gt;session         include         system-auth&lt;br /&gt;session         optional        pam_xauth.so&lt;br /&gt;&lt;br /&gt;now set up the capabilities for the  ping that we are going to use&lt;br /&gt;no legacy effective bit (e), no enabled privilege&lt;br /&gt;&lt;br /&gt;# /usr/sbin/setcap -r ./ping&lt;br /&gt;# /usr/sbin/setcap cap_net_raw=p ./ping&lt;br /&gt;# /usr/sbin/getcap ./ping&lt;br /&gt;./ping = cap_net_raw+p&lt;br /&gt;&lt;br /&gt;can I ping as fpm? no.&lt;br /&gt;&lt;br /&gt;$ id -un&lt;br /&gt;fpm&lt;br /&gt;$ cd ~test&lt;br /&gt;$ ./ping -q -c1 localhost&lt;br /&gt;ping: icmp open socket: Operation not permitted&lt;br /&gt;&lt;br /&gt;can I ping as test? yes.&lt;br /&gt;&lt;br /&gt;$ su - test&lt;br /&gt;Password:&lt;br /&gt;$ id -un&lt;br /&gt;test&lt;br /&gt;$ ./ping -q -c1 localhost&lt;br /&gt;PING localhost.localdomain (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;&lt;br /&gt;--- localhost.localdomain ping statistics ---&lt;br /&gt;1 packets transmitted, 1 received, 0% packet loss, time 0ms&lt;br /&gt;rtt min/avg/max/mdev = 0.024/0.024/0.024/0.000 ms&lt;/pre&gt;&lt;/div&gt;The undocumented &lt;span class='notranslate'&gt;&lt;i&gt;/usr/sbin/capsh&lt;/i&gt;&lt;/span&gt; utility can be used to manage capabilities and reduce the potential for vulnerabilities in shell scripts.&amp;nbsp; It is a simple wrapper around the &lt;span class='notranslate'&gt;&lt;i&gt;bash&lt;/i&gt;&lt;/span&gt; shell which can be used to raise and lower both the &lt;span class='notranslate'&gt;&lt;i&gt;bset&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;pI&lt;/i&gt;&lt;/span&gt; capabilities before invoking &lt;span class='notranslate'&gt;&lt;i&gt;/bin/bash&lt;/i&gt;&lt;/span&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;using the previous ping example which was given CAP_NET_RAW&lt;br /&gt;&lt;br /&gt;$ id -nu&lt;br /&gt;root&lt;br /&gt;$ /usr/sbin/getcap ./ping&lt;br /&gt;./ping = cap_net_raw+ep&lt;br /&gt;&lt;br /&gt;now use capsh to drop CAP_NET_RAW and change to uid 500 (fpm)&lt;br /&gt;the operation is no longer permitted&lt;br /&gt;&lt;br /&gt;$ /usr/sbin/capsh --drop=cap_net_raw --uid=500 --&lt;br /&gt;$ id -nu&lt;br /&gt;fpm&lt;br /&gt;$ ./ping -q -c1 localhost&lt;br /&gt;bash: ./ping: Operation not permitted&lt;br /&gt;&lt;br /&gt;permanently drop CAP_NET_RAW&lt;br /&gt;&lt;br /&gt;$ /usr/sbin/setcap -r ./ping&lt;br /&gt;&lt;br /&gt;and invoke ping using capsh --caps&lt;br /&gt;&lt;br /&gt;$ capsh --caps="cap_net_raw-ep" -- -c "./ping -c1 -q localhost"&lt;br /&gt;PING localhost.localdomain (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;&lt;br /&gt;--- localhost.localdomain ping statistics ---&lt;br /&gt;1 packets transmitted, 1 received, 0% packet loss, time 0ms&lt;br /&gt;rtt min/avg/max/mdev = 0.056/0.056/0.056/0.000 ms&lt;br /&gt; &lt;br /&gt;use capsh to print out capabilities&lt;br /&gt;&lt;br /&gt;$ id -un&lt;br /&gt;fpm&lt;br /&gt;$ /usr/sbin/capsh --print&lt;br /&gt;Current: =&lt;br /&gt;Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,&lt;br /&gt;cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,&lt;br /&gt;cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,&lt;br /&gt;cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,&lt;br /&gt;cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,&lt;br /&gt;cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin&lt;br /&gt;Securebits: 00/0x0&lt;br /&gt; secure-noroot: no (unlocked)&lt;br /&gt; secure-no-suid-fixup: no (unlocked)&lt;br /&gt; secure-keep-caps: no (unlocked)&lt;br /&gt;uid=500&lt;/pre&gt;&lt;/div&gt; There are many other options to &lt;span class='notranslate'&gt;&lt;i&gt;capsh&lt;/i&gt;&lt;/span&gt; and you probably should spend some time experimenting with them.&amp;nbsp; Invoke &lt;span class='notranslate'&gt;&lt;i&gt;capsh&lt;/i&gt;&lt;/span&gt; with the &lt;span class='notranslate'&gt;&lt;i&gt;--help&lt;/i&gt;&lt;/span&gt; option to see the full list.&amp;nbsp; Note that setuid shell scripts do have capabilities.&lt;br /&gt;&lt;br /&gt;All the examples shown above work on &lt;span class='notranslate'&gt;Fedora 10&lt;/span&gt; which uses &lt;span class='notranslate'&gt;&lt;i&gt;libcap 2.10&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; If you wish to experiment on other &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; distributions, it must have a kernel &gt;= 2.6.24 built with &lt;span class='notranslate'&gt;&lt;i&gt;CONFIG_FILE_CAPABILITIES=y&lt;/i&gt;&lt;/span&gt;, a version of &lt;span class='notranslate'&gt;&lt;i&gt;libcap&lt;/i&gt;&lt;/span&gt; &gt;=2.08 and a filesystem that supports extended attributes e.g. &lt;span class='notranslate'&gt;&lt;i&gt;ext3&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;ext4&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Note that &lt;span class='notranslate'&gt;&lt;i&gt;CONFIG_CAPABILITIES=y&lt;/i&gt;&lt;/span&gt; should no longer be required.&lt;br /&gt;&lt;br /&gt;Why are not more people aware of and using &lt;span class='notranslate'&gt;capabilities&lt;/span&gt;?&amp;nbsp; I believe that poor documentation is the primary reason.&amp;nbsp; For example, &lt;span class='notranslate'&gt;Fedora 10&lt;/span&gt; is missing the man pages for &lt;span class='notranslate'&gt;&lt;i&gt;getpcaps&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;capsh&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;pam_cap&lt;/i&gt;&lt;/span&gt;, and the &lt;span class='notranslate'&gt;&lt;a href='http://docs.fedoraproject.org/security-guide/'&gt;Fedora Security Guide&lt;/a&gt;&lt;/span&gt; does not even mention capabilities (or for that matter &lt;span class='notranslate'&gt;ACL&lt;/span&gt;s!)&amp;nbsp; I cannot but help thinking that &lt;span class='notranslate'&gt;capabilities&lt;/span&gt; are treated as the poor cousin to &lt;span class='notranslate'&gt;SELinux&lt;/span&gt; by the &lt;span class='notranslate'&gt;&lt;a href='http://www.fedoraproject.org'&gt;Fedora Project&lt;/a&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Well this blog post is getting a bit long so I am going to stop.&amp;nbsp; I have barely scratched the surface of &lt;span class='notranslate'&gt;capabilities&lt;/span&gt;.&amp;nbsp; After &lt;span class='notranslate'&gt;Fedora 11&lt;/span&gt; ships, I will cover &lt;span class='notranslate'&gt;capabilities&lt;/span&gt; from a programming perspective.&amp;nbsp; Meanwhile, if you want to keep current with what is happening with Linux capabilities,  &lt;span class='notranslate'&gt;Andrew Morgan's &lt;a href='http://sites.google.com/site/fullycapable/'&gt;Fully Capable&lt;/a&gt;&lt;/span&gt; is the one to bookmark.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-3477456496303422666?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/3477456496303422666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/linux-security-capabilities.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3477456496303422666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3477456496303422666'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/linux-security-capabilities.html' title='Linux Security Capabilities'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_IrJjVkDo0pg/SiH4uljFaFI/AAAAAAAAAG8/AqQKT1sE7eI/s72-c/Capture.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-1558472774116425992</id><published>2009-05-26T13:27:00.031-04:00</published><updated>2009-05-28T11:30:54.628-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows parallel filesystem'/><title type='text'>Windows Parallel Filesystems</title><content type='html'>I recently was involved in some development work for a quasi-parallel filesystem for &lt;span class="notranslate"&gt;Microsoft Windows&lt;/span&gt;.&amp;nbsp; As a result of that involvement my interest was piqued and I decided to do so research on what the state of research and development is in the field of parallel filesystems designed specifically for &lt;span class="notranslate"&gt;Microsoft Windows&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;First a quick review of what I mean by a parallel file system.&amp;nbsp; There are any number of different types of parallel file systems available.&amp;nbsp; Some allow multiple systems and applications to share common pools of storage as in a clusered filesystem.&amp;nbsp; Some split the data across two or more nodes to improve access time and redundancy.&amp;nbsp; Other variants split files into lots of small chunks, stores these chunks on different disks in a round-robin fashion, and re-combine them upon reading to get back the original file.&lt;br /&gt;&lt;br /&gt;The earliest instance of &lt;span class="notranslate"&gt;Microsoft Windows&lt;/span&gt;-specific parallel fileystem that I have found to date is the parallel filesystem developed by the &lt;span class="notranslate"&gt;ARGOS&lt;/span&gt; group at &lt;span class="notranslate"&gt;Universidad Carlos 111 de Madrid, Madrid, ES&lt;/span&gt;.&amp;nbsp; This research group developed a prototype of a parallel file system for a network of &lt;span class="notranslate'"&gt;Microsft Windows&lt;/span&gt; nodes which they called &lt;span class="notranslate"&gt;&lt;i&gt;WinPFS&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; They presented their work at &lt;span class="notranslate"&gt;COSET 2004&lt;/span&gt; and a number of other workshops.&amp;nbsp; &lt;span class="notranslate"&gt;&lt;i&gt;WinPFS&lt;/i&gt;&lt;/span&gt; was implemented as a new fileyystem type fully integrated within the &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; kernel.&amp;nbsp; This has the advantage that no modification or recompilation of user applications is needed to take advantage of the parallel filesystem.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_IrJjVkDo0pg/Sh2m2vEi_qI/AAAAAAAAAGk/cHN9mkEFLy0/s1600-h/P3.PNG"&gt;&lt;img style="cursor: pointer; width: 430px; height: 322px;" src="http://4.bp.blogspot.com/_IrJjVkDo0pg/Sh2m2vEi_qI/AAAAAAAAAGk/cHN9mkEFLy0/s320/P3.PNG" alt="" id="BLOGGER_PHOTO_ID_5340608192409960098" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The goal of this research group was to build a parallel file system for networks of &lt;span class="notranslate"&gt;Microsoft Windows&lt;/span&gt; computers using &lt;span class="notranslate"&gt;Microsoft Windows&lt;/span&gt; shared folders to access remote data in parallel.  The implementation is based on file system redirectors which redirect requests to remote nodes using &lt;span class="notranslate"&gt;UNC (Universal Naming Convention)&lt;/span&gt; and the &lt;span class="notranslate"&gt;SMB&lt;/span&gt; and/or &lt;span class="notranslate"&gt;CIFS&lt;/span&gt; protocols.  &lt;span class="notranslate"&gt;WinPFS&lt;/span&gt; is registered as a virtual remote file system and access to remote data is through a new shared folder &lt;span class="notranslate"&gt;&lt;i&gt;\\PFS&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; The basic file operation primatives are: &lt;span class='notranslate'&gt;&lt;i&gt;create&lt;/i&gt;, &lt;i&gt;read&lt;/i&gt;, &lt;i&gt;write&lt;/i&gt;&lt;/span&gt;, and &lt;span class='notranslate'&gt;&lt;i&gt;create directory&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sh2nCry7YVI/AAAAAAAAAGs/q6easS7XyCc/s1600-h/P4.PNG"&gt;&lt;img style="cursor: pointer; width: 430px; height: 322px;" src="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sh2nCry7YVI/AAAAAAAAAGs/q6easS7XyCc/s320/P4.PNG" alt="" id="BLOGGER_PHOTO_ID_5340608397689184594" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The prototype was developed on the &lt;span class="notranslate"&gt;Windows XP&lt;/span&gt; platform, and has been tested with a cluster of seven &lt;span class="notranslate"&gt;Windows XP&lt;/span&gt; nodes and a &lt;span class="notranslate"&gt;Windows 2003 Server&lt;/span&gt; node in various configurations.&amp;nbsp; Maximum throughput for write operations were 250 Mbit/s and 1200 Mbit/s for read operations.&amp;nbsp; The research team reported that the bottleneck for writes was the disks and for reads was the network.&amp;nbsp; As far as I can tell this project is no longer under active development.&lt;br /&gt;&lt;br /&gt;Another interesting experimental parallel file system for &lt;span class="notranslate"&gt;Microsoft Windows&lt;/span&gt; was developed by &lt;span class="notranslate"&gt;Lungpin Yeh, Juei-Ting Sun, Sheng-Kai Hung &amp;amp; Yarsun Hsu&lt;/span&gt; of the &lt;span class="notranslate"&gt;National Tsing-Hua University, ROC&lt;/span&gt;.&amp;nbsp; They presented a paper on their initial implementation at the 2007 High Performance Computation Conference.&lt;br /&gt;&lt;br /&gt;Their implementation consists of three main components: A metadata server, I/O node daemons (IOD) and an API library (&lt;span class="notranslate"&gt;&lt;i&gt;libwpvfs&lt;/i&gt;&lt;/span&gt;) to enable users to develop their own applications on top of the parallel file system.&amp;nbsp; &lt;span class="notranslate"&gt;&lt;i&gt;libwpvfs&lt;/i&gt;&lt;/span&gt;, which uses the &lt;span class="notranslate"&gt;.NET&lt;/span&gt; framework, handles all communications with the metadata server and the IODs and supports six basic file operation primatives: &lt;span class='notranslate'&gt;&lt;i&gt;open&lt;/i&gt;, &lt;i&gt;create&lt;/i&gt;, &lt;i&gt;read&lt;/i&gt;, &lt;i&gt;write&lt;/i&gt;, &lt;i&gt;seek&lt;/i&gt;&lt;/span&gt;, and &lt;span class='notranslate'&gt;&lt;i&gt;close&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sh2kafiYp1I/AAAAAAAAAGU/6uDF0TXUqnA/s1600-h/P1.PNG"&gt;&lt;img style="cursor: pointer; width: 430px; height: 442px;" src="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sh2kafiYp1I/AAAAAAAAAGU/6uDF0TXUqnA/s320/P1.PNG" alt="" id="BLOGGER_PHOTO_ID_5340605508180551506" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The metadata server maps each filename to a unique 64-bit file ID and maintains other information about the file such as striping size, node location and count.&amp;nbsp; While one metadata server is obviously a possible single point of failure, mirroring and redundancy can be used to improve relaibility.&lt;br /&gt;&lt;br /&gt;When an application wants to access a file, the library first connects to the metadata server to acquire the metadata for the file.&amp;nbsp; The library then connects to the appropriate I/O node daemons listed in the metadata, and these node I/O daemons then access the correct file and send the appropriate stripes back to the library for handoff to the calling application.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sh2koJoty1I/AAAAAAAAAGc/TmsMSLXTwRw/s1600-h/P2.PNG"&gt;&lt;img style="cursor: pointer; width: 430px; height: 322px;" src="http://1.bp.blogspot.com/_IrJjVkDo0pg/Sh2koJoty1I/AAAAAAAAAGc/TmsMSLXTwRw/s320/P2.PNG" alt="" id="BLOGGER_PHOTO_ID_5340605742819691346" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Under test conditions with 5 nodes, a maximum of 109 MB/s for writes and 85 MB/s for reads was measured.&lt;br /&gt;&lt;br /&gt;If one of the nodes fails the parallel file system can still work, i.e. the library can make use of the remaining healthy nodes, but the data within the failed node is not available anymore.&amp;nbsp; To overcome this limitation, the research team plan to add node fault tolerance in a future version so that the parallel filesystem will fully work even if some of the I/O nodes fail.&lt;br /&gt;&lt;br /&gt;I am certain that there are other examples of parallel filesystems specifically targeted at networks of &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; computers which have been developed by the academic research community and probably by &lt;span class='notranslate'&gt;Microsoft&lt;/span&gt; itself.&amp;nbsp; As I come across such work, I plan to add details to this post.&lt;br /&gt;&lt;br /&gt;In conclusion, a parallel filesystem can not only provide a larger and/or global storage space for applications by combining storage resources on different nodes but also increase the performance of an application because the application can access files in parallel.&lt;br /&gt;&lt;br /&gt;Traditionally this kind of solution was only available for &lt;span class='notranslate'&gt;Unix&lt;/span&gt; and &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; systems.&amp;nbsp; Examples include &lt;span class='notranslate'&gt;PVFS, GPFS, ParFiSys&lt;/span&gt; and &lt;span class='notranslate'&gt;Vesta&lt;/span&gt;.&amp;nbsp; However, because of the advantages that parallel fileystems can offer, and because of the ubiquity of &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; computers I expect to see a number of commercial parallel filesystems targeted at networks of &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; computers emerge over the next 5 to 10 years. &lt;br /&gt;&lt;br /&gt;P.S. The graphics in this post were copied from published papers of the respective research teams.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-1558472774116425992?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/1558472774116425992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/windows-parallel-filesystems.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1558472774116425992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/1558472774116425992'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/windows-parallel-filesystems.html' title='Windows Parallel Filesystems'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_IrJjVkDo0pg/Sh2m2vEi_qI/AAAAAAAAAGk/cHN9mkEFLy0/s72-c/P3.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-7269372330093872900</id><published>2009-05-23T15:56:00.046-04:00</published><updated>2009-09-06T11:59:48.341-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ksh93 L10N I18N localization message catalog'/><title type='text'>KSH93 Message Localization</title><content type='html'>The current version of &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt; (93t+ 2009-05-01)&lt;/span&gt; supports localization of internal error messages and &lt;span class='notranslate'&gt;&lt;i&gt;getopts&lt;/i&gt;&lt;/span&gt; messages but localization of user messages in shell scripts is flawed.&lt;br /&gt;&lt;br /&gt;For a project I am working on, I needed to be able to supply localized messages for a small number of shell scripts and thus found myself in the bowels of &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; figuring out how to make it so. &lt;br /&gt; &lt;br /&gt;First a word of warning.&amp;nbsp; For the unwary, modifying the source code for &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;libast&lt;/i&gt;&lt;/span&gt; is not for the faint-hearted.&amp;nbsp; It is a fairly complex code base with many levels of abstraction in places.&amp;nbsp; This post assumes that you are reasonably familiar with &lt;span class='notranslate'&gt;&lt;i&gt;libast&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; sources and know how to rebuild &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; from these sources.&lt;br /&gt;&lt;br /&gt;Before getting down to the source code modifications, a discussion of the design decisions and trade offs is in order. The major design decision was to use the &lt;span class='notranslate'&gt;POSIX&lt;/span&gt; message catalog (&lt;span class='notranslate'&gt;&lt;i&gt;catopen(), catgets(), catclose()&lt;/i&gt;&lt;/span&gt;) localization model rather than the &lt;span class='notranslate'&gt;GNU &lt;i&gt;gettext()&lt;/i&gt;&lt;/span&gt; localization model because (1) &lt;span class='notranslate'&gt;&lt;i&gt;libast&lt;/i&gt;&lt;/span&gt; already provided the three &lt;span class='notranslate'&gt;&lt;i&gt;cat*&lt;/i&gt; APIs&lt;/span&gt; as wrappers around the equivalent underlying &lt;span class='notranslate'&gt;&lt;i&gt;libc&lt;/i&gt;&lt;/span&gt; APIs and more importantly (2) I did not want to contaminate the &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; sources which have an &lt;span class='notranslate'&gt;Common Public Licence V1.0&lt;/span&gt; license with &lt;span class='notranslate'&gt;GNU &lt;i&gt;gettext()&lt;/i&gt;&lt;/span&gt; sources which have a GPL license.&lt;br /&gt;&lt;br /&gt;The second major design decision I made was that the message catalogs would have the same name as the shell script and and would reside in the system default message catalog location rather than locally (although this can be overwritten by the &lt;span class='notranslate'&gt;&lt;i&gt;NLSPATH&lt;/i&gt;&lt;/span&gt; environmental variable.)&amp;nbsp; My current development system is Fedora 11 (Leonidas) x86_64.&amp;nbsp; There the default location for localized messages is &lt;span class='notranslate'&gt;&lt;i&gt;/usr/share/locale/%l/LC_MESSAGES/&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Thus, for example, the french message catalog for a shell script named &lt;span class='notranslate'&gt;&lt;i&gt;fpm&lt;/i&gt;&lt;/span&gt; would be &lt;span class='notranslate'&gt;&lt;i&gt;/usr/share/locale/fr/LC_MESSAGES/fpm&lt;/i&gt;&lt;/span&gt; assuming &lt;span class='notranslate'&gt;&lt;i&gt;LC_MESSAGES&lt;/i&gt;&lt;/span&gt; was set to &lt;span class='notranslate'&gt;&lt;i&gt;fr_FR.UTF-8&lt;/i&gt;&lt;/span&gt; or something equivalent.&lt;br /&gt;&lt;br /&gt;The final major design decision I made was not to require the use of set and message numbers for identifying message strings as is normal in the &lt;span class='notranslate'&gt;POSIX&lt;/span&gt; message catalog model but rather to follow the &lt;span class='notranslate'&gt;&lt;i&gt;gettext()&lt;/i&gt;&lt;/span&gt; model whereby a message string conveys sufficient information to find it's equivalent localized string.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The way this works is that you must provide a &lt;span class='notranslate'&gt;C&lt;/span&gt; locale message catalog with a single set of messages (set 1) which &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; reads to determine the message number.&amp;nbsp; It then uses that message number to retrieve the same message from set 1 of the localized message catalog.&amp;nbsp; This means that the C locale message catalog and the various other localized message catalogs must be kept synchronized for correct localized message retrieval.  Note that &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; defaults to the original message string if it cannot find that message string in the &lt;span class='notranslate'&gt;C&lt;/span&gt; locale message catalog or in the localized message catalog.&lt;br /&gt;&lt;br /&gt;Modifications are only necessary to two source files.&amp;nbsp; Add the following function to &lt;span class='notranslate'&gt;&lt;i&gt;.../lib/libast/translate.c&lt;/i&gt;&lt;/span&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;/* &lt;br /&gt; * Support internationalized messages in $"..." format&lt;br /&gt; * Assumes that catalog name is exactly the same as the script name &lt;br /&gt; */&lt;br /&gt;char*&lt;br /&gt;fpm_translate(const char* cmd, const char* msg)&lt;br /&gt;{&lt;br /&gt;    register char*  r;&lt;br /&gt;    register char*  u;&lt;br /&gt;    char *          t;&lt;br /&gt;    nl_catd         d;&lt;br /&gt;    int             n;&lt;br /&gt;    int             msgno;&lt;br /&gt;    char *          j;&lt;br /&gt;    char *          s;&lt;br /&gt;&lt;br /&gt;    r = (char*)msg;&lt;br /&gt;&lt;br /&gt;    if (!msg) return NiL;&lt;br /&gt;&lt;br /&gt;    if (cmd &amp;&amp; (t = strrchr(cmd, '/')))&lt;br /&gt;        cmd = (const char*)(t + 1);&lt;br /&gt;    &lt;br /&gt;    /* first locate the message in the C locale and determine message number */&lt;br /&gt;    u = setlocale(LC_MESSAGES, NiL);&lt;br /&gt;    j = strdup(u);&lt;br /&gt;    setlocale(LC_MESSAGES, "C");&lt;br /&gt;    if (( d = find("C", cmd)) != NOCAT )&lt;br /&gt;    {&lt;br /&gt;        n = 0;&lt;br /&gt;        msgno = 0;&lt;br /&gt;        for (;;)&lt;br /&gt;        {&lt;br /&gt;            n++;&lt;br /&gt;            if ((s = catgets(d, 1, n, NULL)) == NULL)&lt;br /&gt;                break;&lt;br /&gt;            if (!strcmp(msg, s))&lt;br /&gt;            {&lt;br /&gt;                msgno = n;&lt;br /&gt;                break;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        catclose(d);&lt;br /&gt;    }&lt;br /&gt;    setlocale(LC_MESSAGES, j);&lt;br /&gt;    free(j);&lt;br /&gt;&lt;br /&gt;    /* then use that message number to retrieve equivalent L10N message */&lt;br /&gt;    if (( d = find(setlocale(LC_MESSAGES,NiL), cmd)) != NOCAT )&lt;br /&gt;    {&lt;br /&gt;        s = catgets(d, 1,  msgno, msg);&lt;br /&gt;        r = strdup(s);&lt;br /&gt;        catclose(d);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return r;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;and modify &lt;span class='notranslate'&gt;&lt;i&gt;sh_endword()&lt;/i&gt;&lt;/span&gt; in &lt;span class='notranslate'&gt;&lt;i&gt;.../cmd/ksh93/sh/lex.c&lt;/i&gt;&lt;/span&gt; as follows:&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#if NO_LOCALIZED_MESSAGES &lt;br /&gt;#if ERROR_VERSION &gt;= 20000317L&lt;br /&gt;                     msg = ERROR_translate(0,error_info.id,0,ep);&lt;br /&gt;#else&lt;br /&gt;#   if ERROR_VERSION &gt;= 20000101L&lt;br /&gt;                     msg = ERROR_translate(error_info.id,ep);&lt;br /&gt;#   else&lt;br /&gt;                     msg = ERROR_translate(ep,2);&lt;br /&gt;#   endif&lt;br /&gt;#endif&lt;br /&gt;#else&lt;br /&gt;                     msg = fpm_translate(shp-&gt;st.cmdname, ep);&lt;br /&gt;#endif&lt;/pre&gt;&lt;/div&gt;Then rebuild &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; using &lt;span class='notranslate'&gt;&lt;i&gt;.../bin/package make&lt;/i&gt;&lt;/span&gt; or with your own custom build script.&lt;br /&gt;&lt;br /&gt;Here is a simple shell script (&lt;span class='notranslate'&gt;&lt;i&gt;demo&lt;/i&gt;&lt;/span&gt;) which has a localized French message catalog.&amp;nbsp; Use the system &lt;span class='notranslate'&gt;&lt;i&gt;gencat&lt;/i&gt;&lt;/span&gt; to compile the two message catalogs, not UWIN's gencat.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ cat demo&lt;br /&gt;#!/bin/ksh&lt;br /&gt;name="Finnbarr"&lt;br /&gt;echo "ksh93 message translation example"&lt;br /&gt;echo  $"Hello"&lt;br /&gt;print $"Goodbye"&lt;br /&gt;printf $"Welcome %s\n" $name&lt;br /&gt;print $"No Translation available"&lt;br /&gt;&lt;br /&gt;$ cat demo.msg.c&lt;br /&gt;$quote "&lt;br /&gt;$set 1  This is the C locale message set&lt;br /&gt;1 "Hello"&lt;br /&gt;2 "Goodbye"&lt;br /&gt;3 "Welcome %s\\n"&lt;br /&gt;&lt;br /&gt;$ cat demo.msg.fr&lt;br /&gt;$quote "&lt;br /&gt;$set 1  This is the French locale message set&lt;br /&gt;1 "Bonjour"&lt;br /&gt;2 "Au Revoir"&lt;br /&gt;3 "Bienvenu %s\\n"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;Note the requirement to guard newlines with an backslash. &lt;br /&gt;&lt;br /&gt;Here is an example of the output from &lt;span class='notranslate'&gt;&lt;i&gt;demo&lt;/i&gt;&lt;/span&gt; under various locale settings.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ locale&lt;br /&gt;LANG=en_US.UTF-8&lt;br /&gt;LC_CTYPE="en_US.UTF-8"&lt;br /&gt;LC_NUMERIC="en_US.UTF-8"&lt;br /&gt;LC_TIME="en_US.UTF-8"&lt;br /&gt;LC_COLLATE="en_US.UTF-8"&lt;br /&gt;LC_MONETARY="en_US.UTF-8"&lt;br /&gt;LC_MESSAGES="en_US.UTF-8"&lt;br /&gt;LC_PAPER="en_US.UTF-8"&lt;br /&gt;LC_NAME="en_US.UTF-8"&lt;br /&gt;LC_ADDRESS="en_US.UTF-8"&lt;br /&gt;LC_TELEPHONE="en_US.UTF-8"&lt;br /&gt;LC_MEASUREMENT="en_US.UTF-8"&lt;br /&gt;LC_IDENTIFICATION="en_US.UTF-8"&lt;br /&gt;LC_ALL=&lt;br /&gt; &lt;br /&gt;$ ./demo&lt;br /&gt;A simple ksh93 message translation example&lt;br /&gt;Hello&lt;br /&gt;Goodbye&lt;br /&gt;Welcome Finnbarr&lt;br /&gt;No translated message&lt;br /&gt;&lt;br /&gt;$ unset LANG&lt;br /&gt;$ locale&lt;br /&gt;LANG=&lt;br /&gt;LC_CTYPE="POSIX"&lt;br /&gt;LC_NUMERIC="POSIX"&lt;br /&gt;LC_TIME="POSIX"&lt;br /&gt;LC_COLLATE="POSIX"&lt;br /&gt;LC_MONETARY="POSIX"&lt;br /&gt;LC_MESSAGES="POSIX"&lt;br /&gt;LC_PAPER="POSIX"&lt;br /&gt;LC_NAME="POSIX"&lt;br /&gt;LC_ADDRESS="POSIX"&lt;br /&gt;LC_TELEPHONE="POSIX"&lt;br /&gt;LC_MEASUREMENT="POSIX"&lt;br /&gt;LC_IDENTIFICATION="POSIX"&lt;br /&gt;LC_ALL=&lt;br /&gt; &lt;br /&gt;$ ./demo&lt;br /&gt;A simple ksh93 message translation example&lt;br /&gt;Hello&lt;br /&gt;Goodbye&lt;br /&gt;Welcome Finnbarr&lt;br /&gt;No translated message&lt;br /&gt; &lt;br /&gt;$ export LC_MESSAGES=fr_FR.UTF-8&lt;br /&gt;$ locale&lt;br /&gt;LANG=&lt;br /&gt;LC_CTYPE="POSIX"&lt;br /&gt;LC_NUMERIC="POSIX"&lt;br /&gt;LC_TIME="POSIX"&lt;br /&gt;LC_COLLATE="POSIX"&lt;br /&gt;LC_MONETARY="POSIX"&lt;br /&gt;LC_MESSAGES=fr_FR.UTF-8&lt;br /&gt;LC_PAPER="POSIX"&lt;br /&gt;LC_NAME="POSIX"&lt;br /&gt;LC_ADDRESS="POSIX"&lt;br /&gt;LC_TELEPHONE="POSIX"&lt;br /&gt;LC_MEASUREMENT="POSIX"&lt;br /&gt;LC_IDENTIFICATION="POSIX"&lt;br /&gt;LC_ALL=&lt;br /&gt;&lt;br /&gt;$ ./demo&lt;br /&gt;A simple ksh93 message translation example&lt;br /&gt;Bonjour&lt;br /&gt;Au Revoir&lt;br /&gt;Bienvenu Finnbarr&lt;br /&gt;No translated message&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt; Well, that's about all for now.&amp;nbsp; I have provided sufficient information for you to try out localized message strings with &lt;span class='notranslate'&gt;ksh93&lt;/span&gt; for yourself if this is something you need.&lt;br /&gt;&lt;br /&gt;Note that this is still a work in progress.&amp;nbsp; I have not yet tested support for multibyte message catalogs (I am not sure if &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; even works in multibyte locales!).&amp;nbsp; Since I have hijacked the existing hook for error message catalogs, I probably should figure out how to get localization of &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; error messages working again.&amp;nbsp; There may be memory leaks or boundary conditions that I am unaware of.&amp;nbsp; Therefore if you are going to use this modification in a production environment, test and test again!&lt;br /&gt;&lt;br /&gt;A useful future enhancement would be to decouple the name of the message catalog from the name of the shell script and also allow message set numbers other than 1.&amp;nbsp; This could be achieved by using a pair of environmental variables or by means of a &lt;span class='notranslate'&gt;&lt;i&gt;msgcat&lt;/i&gt;&lt;/span&gt; compound variable where &lt;span class='notranslate'&gt;&lt;i&gt;msgcat.name&lt;/i&gt;&lt;/span&gt; is the name of the message catalog to be used and &lt;span class='notranslate'&gt;&lt;i&gt;msgcat.set&lt;/i&gt;&lt;/span&gt; is the actual message set to be used. &lt;br /&gt;&lt;br /&gt;Have a great Memorial Day, and take a few moments to remember those who have sacrificed so that we can be free.&lt;br /&gt;&lt;br /&gt;Comments and feedback are welcome as always.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;[2009-09-05] Recently I spent some more time in the bowels of the AST library (libast) and made an interesting discovery regarding message catalog support for shell scripts. I discovered that &lt;span class='notranslate'&gt;&lt;i&gt;../lib/libast/misc/translate.c&lt;/i&gt;&lt;/span&gt; is where the real problem is located. The &lt;span class='notranslate'&gt;&lt;i&gt;translate()&lt;/i&gt;&lt;/span&gt; function contains a call to &lt;span class='notranslate'&gt;&lt;i&gt;catget()&lt;/i&gt;&lt;/span&gt; but only for message set number 3 (three). This is hardcoded into this call via the AST_MESSAGE_SET define in &lt;span class='notranslate'&gt;&lt;i&gt;../libast/include/ast_std.h&lt;/i&gt;&lt;/span&gt;. So unless you define &lt;span class='notranslate'&gt;&lt;i&gt;$set 3&lt;/i&gt;&lt;/span&gt; in your message catalog, internationalization or localization of a &lt;span class='notranslate'&gt;ksh93&lt;/span&gt; shell script simply will not work.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-7269372330093872900?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/7269372330093872900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/ksh93-message-localization.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/7269372330093872900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/7269372330093872900'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/ksh93-message-localization.html' title='KSH93 Message Localization'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-3632910900287516066</id><published>2009-05-06T11:14:00.002-04:00</published><updated>2009-05-23T16:19:14.390-04:00</updated><title type='text'>Charles Merton Richmond RIP</title><content type='html'>&amp;nbsp;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_IrJjVkDo0pg/SgMPAM9s-sI/AAAAAAAAAF8/S4wiV6EmKjQ/s1600-h/cmr1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 440px; height: 600px;" src="http://2.bp.blogspot.com/_IrJjVkDo0pg/SgMPAM9s-sI/AAAAAAAAAF8/S4wiV6EmKjQ/s320/cmr1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5333122879891241666" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yesterday my old friend and collegue Charles Merton Richmond (Charlie) died at home in Cebu PH of a massive heart attack. &lt;br /&gt;&lt;br /&gt;Charlie and I go back a long time.&amp;nbsp; We first met when Lotus Development set up a UNIX porting group in Dublin, Ireland.&amp;nbsp; Charlie was Digital Equipment Corporation's on-site go-to person for the port of Lotus 1-2-3 to DEC Ultrix.&amp;nbsp;  At that time Charlie was single-handedly raising his son, Keith, and brought him with him to Dublin for the 6 month assignment.  &lt;br /&gt; &lt;br /&gt;I was a principal software engineer responsible for the Ultrix, HP and SCO UNIX ports of 1-2-3 so we quickly came to know each other pretty well.&amp;nbsp; The UNIX porting group was a lively and interesting group with many characters and we often had a good evening at the Grave Diggers in Glasnevin.&amp;nbsp; Charlie thoroughly enjoyed Irish pubs and restaurants.&amp;nbsp; The older and more oddball the pub or restaurant the happier he was.&amp;nbsp; He could not get over the fact that the Irish (and English) would put hot curry sauce over french fies or deep fry Mars bars as a dessert.&lt;br /&gt;&lt;br /&gt;When the Ultrix port was finished Charles and his son moved back to their high rise apartment in downtown Boston.&amp;nbsp; Since I used visit the Lotus headquarters in Cambridge on a regular basis, I would frequently meet up with Charlie for sushi and drinks.&amp;nbsp; Charles was a true sushi aficionado and I learned a lot about the finer points of sushi and other Japanese foods from him.&lt;br /&gt;&lt;br /&gt;Charlie was the person who recruited me to go work fulltime for Digital Equipment Corporation.&amp;nbsp; We ended up working together on localization and internationalization issues for nearly 18 months in Manalapan, NJ and Nashua, NH.&amp;nbsp; He was an amazing driver.&amp;nbsp; Many times we left Manapan NJ at 3.30 in the afternoon and would make downtown Boston by 7.30 that evening.&lt;br /&gt;&lt;br /&gt;Charlie also loved motorbikes but was badly injured by a careless driver on the Southeast Expressway in early 2000 while on his way to work.&amp;nbsp; During a followup visit to a specialist, he was again badly injured by a vehicle whose driver failed to see him on the crosswalk!&lt;br /&gt;&lt;br /&gt;Over the years Charlie and I worked together on various projects.&amp;nbsp; In 2004 he moved to Cebu where he met and married a wonderful Filipana woman named Ashley.&amp;nbsp; Last year I worked with Charlie in Cebu on a couple of projects.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Charlie and I had a tentative schedule to again work together on a project in Cebu later this year and I was really looking forward to spending time with him again.&amp;nbsp; Alas, that will not now happen. &lt;br /&gt;&lt;br /&gt;I shall miss you, Charlie.&lt;br /&gt;&lt;br /&gt;Rest in peace.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-3632910900287516066?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/3632910900287516066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/charles-richmond-rip.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3632910900287516066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/3632910900287516066'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/charles-richmond-rip.html' title='Charles Merton Richmond RIP'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_IrJjVkDo0pg/SgMPAM9s-sI/AAAAAAAAAF8/S4wiV6EmKjQ/s72-c/cmr1.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-7637540342442613592</id><published>2009-04-30T09:38:00.000-04:00</published><updated>2009-05-23T20:49:51.771-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux Porting WaitForSingleObject WaitForMultipleObject thread event'/><title type='text'>Porting WaitForSingleObject to Linux - Part 2</title><content type='html'>In my last post I discussed the use of &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; in relation to &lt;span class='notranslate'&gt;&lt;i&gt;mutexes&lt;/i&gt;&lt;/span&gt; and possible ways to implement equivalent functionality when porting such code to &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt;.&amp;nbsp; In this post I will describe the use of this &lt;span class='notranslate'&gt;API&lt;/span&gt; with event objects in &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; and suggest possible ways of posting such code to &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; or &lt;span class='notranslate'&gt;Unix&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;First, some background on event objects.&amp;nbsp; An event object is just another type of &lt;span class='notranslate'&gt;Windows&lt;/span&gt; kernel &lt;span class="notranslate"&gt;&lt;i&gt;dispatcher object&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; From a coding prespective, an event object is a &lt;i&gt;synchronization&lt;/i&gt; object which encapsulates one or more kernel &lt;span class='notranslate'&gt;dispatcher objects and whose synchronization semantics are accessable via &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; and its cousins.&amp;nbsp; At any given time a synchronization object is either &lt;span class='notranslate'&gt;&lt;i&gt;nonsignaled&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;signaled&lt;/i&gt;&lt;/span&gt;, i.e. the object can only be in one of two possible states. &lt;br /&gt;&lt;br /&gt;All of the &lt;span class='notranslate'&gt;&lt;i&gt;WaitFor&lt;/i&gt;&lt;/span&gt; family of APIs including &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleobject&lt;/i&gt;&lt;/span&gt; wait on an object handle or handles until some specified criteria is met.&amp;nbsp; The two basic criteria for all these &lt;span class='notranslate'&gt;APIs&lt;/span&gt; are the signaled state of the object on whose handle it is waiting and a time-out value.&amp;nbsp; Thus a thread which calls this API waits till the specified object enters the &lt;span class='notranslate'&gt;&lt;i&gt;signaled state&lt;/i&gt;&lt;/span&gt; or the specified time-out has expired.&amp;nbsp; Little or no CPU time is used when such a thread is in the wait state.&lt;br /&gt;&lt;br /&gt;In the case of events, a &lt;span class='notranslate'&gt;&lt;i&gt;CreateEvent&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;OpenEvent&lt;/i&gt;&lt;/span&gt; returns a handle to an event object.&amp;nbsp; When an event is in the &lt;span class='notranslate'&gt;&lt;i&gt;signaled&lt;/i&gt;&lt;/span&gt; state it means that that the event has the capacity to release one or more threads waiting for this particular event to be signaled.&amp;nbsp; When an event is in the &lt;span class='notranslate'&gt;&lt;i&gt;nonsignaled&lt;/i&gt;&lt;/span&gt; state it will not release any waiting thread.&amp;nbsp; Initially the state of an event is &lt;span class='notranslate'&gt;&lt;i&gt;nonsignaled&lt;/i&gt;&lt;span&gt;.&amp;nbsp; An event object's state is set explicitly to &lt;span class='notranslate'&gt;&lt;i&gt;signaled&lt;/i&gt;&lt;/span&gt; by &lt;span class='notranslate'&gt;&lt;i&gt;SetEvent&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;PulseEvent&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Event objects are also used in overlapped operations such as reading from a socket, in which case the event object state is set to &lt;span class='notranslate'&gt;&lt;i&gt;signaled&lt;/i&gt;&lt;/span&gt; by the kernel rather than by an application.&lt;br /&gt;&lt;br /&gt;Events also come in two &lt;span class='notranslate'&gt;&lt;i&gt;reset&lt;/i&gt;&lt;/span&gt; types.&amp;nbsp; If an event is a &lt;span class='notranslate'&gt;&lt;i&gt;manual-reset&lt;/i&gt;&lt;/span&gt; event, then all &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObjects&lt;/i&gt;&lt;/span&gt; return that wait for that event if so configured.&amp;nbsp; In other words a &lt;span class='notranslate'&gt;&lt;i&gt;manual-reset&lt;/i&gt;&lt;/span&gt; event can trigger action by one or more &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; or its cousins.&amp;nbsp;  A &lt;span class='notranslate'&gt;&lt;i&gt;manual-reset&lt;/i&gt;&lt;/span&gt; event object's state must be reset explicitly to &lt;span class='notranslate'&gt;&lt;i&gt;nonsignaled&lt;/i&gt;&lt;/span&gt; by &lt;span class='notranslate'&gt;&lt;i&gt;ResetEvent&lt;/i&gt;&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;For an &lt;span class='notranslate'&gt;&lt;i&gt;auto-reset&lt;/i&gt;&lt;/span&gt; event object, &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; and it's relations reset the state of the event object to &lt;span class='notranslate'&gt;&lt;i&gt;nonsignaled&lt;/i&gt;&lt;/span&gt; before returning.&amp;nbsp; While an &lt;span class='notranslate'&gt;&lt;i&gt;auto-reset&lt;/i&gt;&lt;/spam&gt; event is guaranteed to set the event to &lt;span class='notranslate'&gt;&lt;i&gt;nonsignaled&lt;/i&gt;&lt;/span&gt; and release a single thread that is waiting on the event to occu, if more than one thread is waiting for this particular event to occur then which particular thread is released is random.&lt;br /&gt;&lt;br /&gt;Consider the following skeleton &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; application.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;HANDLE hEvent;&lt;br /&gt;HANDLE hMutex;&lt;br /&gt;HANLE  hThread;&lt;br /&gt;....&lt;br /&gt;BOOLEAN  Run = TRUE;&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;main()&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    hMutex = CreateMutex(0, FALSE, NULL);&lt;br /&gt;    hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);&lt;br /&gt;    .....&lt;br /&gt;    hThread = CreateThread( NULL, 0 (LPTHREAD_START_ROUTINE)SendThread, 0, 0, 0);&lt;br /&gt;    .....&lt;br /&gt;&lt;br /&gt;    /* produce and post messages */&lt;br /&gt;    .....&lt;br /&gt;&lt;br /&gt;    /* clean up and exit */&lt;br /&gt;    CloseHandle(hEvent);&lt;br /&gt;    CloseHandle(hMutex);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DWORD SendThread (LPVOID Parm)&lt;br /&gt;{&lt;br /&gt;    do {&lt;br /&gt;          /* wait for the event */&lt;br /&gt;          WaitForSingleObject( hEvent, INFINITE );&lt;br /&gt;&lt;br /&gt;          /* send the message */&lt;br /&gt;          ....&lt;br /&gt;          ....&lt;br /&gt;          /* lock message queue and delete message */&lt;br /&gt;          WaitForSingleObject( hMutex, INFINITE );&lt;br /&gt;          .....&lt;br /&gt;          .....&lt;br /&gt;          ReleaseMutex( hMutex );&lt;br /&gt;&lt;br /&gt;    } while ( Run };&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PostMessage( PMESSAGE Message )&lt;br /&gt;{&lt;br /&gt;    /* lock message queue and add message */&lt;br /&gt;    WaitForSingleObject( hMutex, INFINITE );&lt;br /&gt;    .....&lt;br /&gt;    .....&lt;br /&gt;    ReleaseMutex( hMutex );&lt;br /&gt;&lt;br /&gt;    /* signal SendThread that there is a message in the queue */&lt;br /&gt;    SetEvent( hEvent );&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;Assume that the purpose of this application, for whatever reason, is to broadcast UDP messages.&amp;nbsp; A separate thread of execution, i.e &lt;span class='notranslate'&gt;&lt;i&gt;SendThread&lt;/i&gt;&lt;/span&gt;, is created to handle the actual broadcasting.&amp;nbsp; It simple takes whatever messages are in the send message queue amd broadcasts them.&amp;nbsp;  If there are no messages in the message queue, the thread waits (yields) until it is signalled that there is one or more messages waiting to be broadcast.&lt;br /&gt;&lt;br /&gt;Here is the same application code after it was ported to &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; using &lt;span class='notranslate'&gt;POSIX&lt;/span&gt; theads.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;pthread_cond_t   hEvent;&lt;br /&gt;pthread_mutex_t  hMutex;&lt;br /&gt;pthread_t        hThread;&lt;br /&gt;....&lt;br /&gt;BOOLEAN  Run = TRUE;&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;main()&lt;br /&gt;{&lt;br /&gt;    pthread_mutexattr_t  mattr;&lt;br /&gt;    pthread_attr_t       attr;&lt;br /&gt;&lt;br /&gt;    /* initialize condition variable */&lt;br /&gt;    pthread_cond_init( &amp;hEvent, NULL);&lt;br /&gt;&lt;br /&gt;    /* initialize mutex as a recursive type */&lt;br /&gt;    pthread_mutexattr_init( &amp;mattr );&lt;br /&gt;    pthread_mutexattr_settype( &amp;mattr, PTHREAD_MUTEX_RECURSIVE );&lt;br /&gt;    pthread_mutex_init( &amp;hMutex, &amp;mattr );&lt;br /&gt;&lt;br /&gt;    /* create thread as detached and process scope */&lt;br /&gt;    pthread_attr_init( &amp;attr);&lt;br /&gt;    pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_DETACHED);&lt;br /&gt;    pthread_attr_setscope(&amp;attr, PTHREAD_SCOPE_PROCESS);&lt;br /&gt;    pthread_create( &amp;hThread, &amp;attr, SendThread, 0);&lt;br /&gt;&lt;br /&gt;    .....&lt;br /&gt;    /* produce and post messages */&lt;br /&gt;    .....&lt;br /&gt;&lt;br /&gt;    /* clean up and exit */&lt;br /&gt;    pthread_attr_destroy( &amp;attr );&lt;br /&gt;    pthread_cond_destroy( &amp;hEvent );&lt;br /&gt;    pthread_mutex_destroy( &amp;hMutex );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void *&lt;br /&gt;SendThread ( void *Parm )&lt;br /&gt;{&lt;br /&gt;    do {&lt;br /&gt;          /* wait for the event */&lt;br /&gt;          pthread_mutex_lock( &amp;hMutex );&lt;br /&gt;          pthread_cond_wait( &amp;hEvent, &amp;hMutex );&lt;br /&gt;          pthread_mutex_unlock( &amp;hMutex );&lt;br /&gt;&lt;br /&gt;          /* send the message */&lt;br /&gt;          ....&lt;br /&gt;          ....&lt;br /&gt;&lt;br /&gt;          /* lock message queue and delete message */&lt;br /&gt;          pthread_mutex_lock( &amp;hMutex );&lt;br /&gt;          .....&lt;br /&gt;          .....&lt;br /&gt;          pthread_mutex_unlock( &amp;hMutex );&lt;br /&gt;&lt;br /&gt;    } while ( Run };&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PostMessage( PMESSAGE Message )&lt;br /&gt;{&lt;br /&gt;    /* lock message queue and add message */&lt;br /&gt;    pthread_mutex_lock( &amp;hMutex );&lt;br /&gt;    .....&lt;br /&gt;    .....&lt;br /&gt;    pthread_cond_signal( &amp;hEvent );    /* signal SendThread */&lt;br /&gt;    pthread_mutex_unlock( &amp;hMutex );&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;                &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*** UNDER CONSTRUCTION ***&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-7637540342442613592?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/7637540342442613592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/porting-waitforsingleobject-to-linux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/7637540342442613592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/7637540342442613592'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/05/porting-waitforsingleobject-to-linux.html' title='Porting WaitForSingleObject to Linux - Part 2'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-4805605294690404253</id><published>2009-04-29T16:01:00.000-04:00</published><updated>2009-05-24T10:10:37.222-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux Windows Porting WaitForSingleObject  NtWaitForSingleObject WaitForMultipleObject NtWaitForMultipleObject threads mutex mutant'/><title type='text'>Porting WaitForSingleObject to Linux - Part 1</title><content type='html'>Recently I was involved in porting a 32-bit application which was initially written for &lt;span class='notranslate'&gt;Microsoft Windows NT&lt;/span&gt; to GNU/Linux.&amp;nbsp; This application contained a large number of calls to &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms648412(VS.85).aspx'&gt;NtWaitForSingleObject&lt;/a&gt;&lt;/i&gt;&lt;span&gt; and a smaller number of calls to &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms687025(VS.85).aspx'&gt;NtWaitForMultipleObject&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Now anybody who has had to port code containing more than a few instances of these particular &lt;span class='notranslate'&gt;Win32 APIs&lt;/span&gt;, or their close cousins &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms687036(VS.85).aspx'&gt;WaitForSingleObjectEx&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx'&gt;MsgWaitForMultipleObjects&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms684245(VS.85).aspx'&gt;MsgWaitForMultipleObjectsEx&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;, etc. to &lt;span class='notranslate'&gt;Unix&lt;/span&gt; or &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; is probably already shuddering with the recollection of long arduous days and nights of trial and error coding to try and correctly mimic the semantics and functionality of these particular &lt;span class='notranslate'&gt;Microsoft Windows&lt;/span&gt; specific APIs, but for the reader who has not yet had to attempt to port such an application, this post and my next post may help you save your sanity (and possibly your hair!) sometime in the future.&lt;br /&gt;&lt;br /&gt;By the way, both of these &lt;span class='notranslate'&gt;APIs&lt;/span&gt; are marked &lt;span class='notranslate'&gt;&lt;i&gt;deprecated&lt;/i&gt;&lt;/span&gt; in &lt;a href='http://msdn.microsoft.com/en-us/default.aspx'&gt;MSDN&lt;/a&gt; by Microsoft but still work as expected in Windows NT and Windows XP.&amp;nbsp; I am not sure about &lt;span class='notranslate'&gt;Windows Vista&lt;/span&gt; or &lt;span class='notranslate'&gt;Windows 7&lt;/span&gt; as I have not tested them on these operating systems.&amp;nbsp; The two deprecated &lt;span class='notranslate'&gt;APIs&lt;/span&gt; have been replaced by the equivalant &lt;span class='notranslate'&gt;APIs &lt;i&gt;&lt;a href= 'http://msdn.microsoft.com/en-us/library/aa450988.aspx'&gt;WaitForSingleObject&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms687028(VS.85).aspx'&gt; WaitForMultipleObject&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; respectively.&amp;nbsp; For the remainder of this post I shall just discuss the replacement &lt;span class='notranslate'&gt;APIs&lt;/span&gt; but most of what I say will be valid for either the deprecated or the replacement &lt;span class='notranslate'&gt;API&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;On first examination &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; seems fairly benign.&amp;nbsp; The description in &lt;span class='notranslate'&gt;MSDN&lt;/span&gt; states that &lt;i&gt;"This function returns when the specified object is in the signaled state or when the time-out interval elapses"&lt;/i&gt;.&amp;nbsp; Sounds like a fairly simple and innocuous &lt;span class='notranslate'&gt;API&lt;/span&gt;, right?&amp;nbsp; Maybe something similar to the &lt;span class='notranslate'&gt;POSIX.1 API&lt;/span&gt; &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://www.opengroup.org/onlinepubs/000095399/functions/pthread_cond_timedwait.html'&gt;pthread_cond_timedwait&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Well, you are dead wrong and this post and the following will explain why.&lt;br /&gt;&lt;br /&gt;&lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; and its cousins can wait for a signal from any or all of the following "objects": change notification, console input, event, job, memory resource notification, mutex, process, semaphore, thread and waitable timer and in limited circumstances on files and file I/O.&amp;nbsp; When appropriately signaled, a thread is unblocked and continues.&amp;nbsp; No published standardized &lt;span class='notranslate'&gt;API&lt;/span&gt; in the &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; or &lt;span class='notranslate'&gt;Unix&lt;/span&gt; world comes come to handling this range of objects in a single &lt;span class='notranslate'&gt;API&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This is probably the one single area where a &lt;span class='notranslate'&gt;Win32 API&lt;/span&gt; is better designed than the &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; or &lt;span class='notranslate'&gt;Unix API&lt;/span&gt; set.&amp;nbsp; In &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; and &lt;span class='notranslate'&gt;Unix&lt;/span&gt; there are specific &lt;span class='notranslate'&gt;APIs&lt;/span&gt; to wait for different kinds of events: &lt;span class='notranslate'&gt;&lt;i&gt;select&lt;/i&gt;&lt;/span&gt; waits for &lt;span class='notranslate'&gt;I/O&lt;/span&gt; events such as &lt;span class='notranslate'&gt;sockets&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;semop&lt;/i&gt;&lt;/span&gt; waits for &lt;span class='notranslate'&gt;semaphores, &lt;span class='notranslate'&gt;&lt;i&gt;wait&lt;/i&gt;&lt;/span&gt; waits for child processes, etc.&lt;br /&gt;&lt;br /&gt;Unfortunately the semantics of &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; and its cousins varies depending on the different object types.&amp;nbsp; For example, it destroys a thread, but only unlocks a mutex.&amp;nbsp; For this reason understanding &lt;span class='notranslate'&gt;Win32&lt;/span&gt; source code from the viewpoint of porting to &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; can be much more difficult.&lt;br /&gt;&lt;br /&gt;Our first example, i.e. locking a mutex (or &lt;span class='notranslate'&gt;&lt;i&gt;mutants&lt;/i&gt;&lt;span&gt; as they are sometimes called by &lt;span class='notranslate'&gt;Windows&lt;/span&gt; programmers), is probably the simplest use of &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; and is relatively easy to port to GNU/Linux.&amp;nbsp; Consider the following Windows code which creates 2 threads, and a mutex to control access to an integer variable &lt;i&gt;x&lt;/i&gt;&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;INTEGER x;&lt;br /&gt;HANDLE  hMutex;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;void function1() &lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   WaitForSingleObject(hMutex,INFINATE);&lt;br /&gt;   x= 5;&lt;br /&gt;   ReleaseMutex(hMutex);&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void funtion2() &lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   WaitForSingleObject(hMutex,INFINATE);&lt;br /&gt;   x = 12;&lt;br /&gt;   ReleaseMutex(hMutex);&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int WINAPI WinMain(...) &lt;br /&gt;{&lt;br /&gt;   hMutex = CreateMutex(NULL,FALSE,NULL);&lt;br /&gt;   ....&lt;br /&gt;   HANDLE hThread1 = CreateThread(..., (LPTHREAD_START_ROUTINE)function1, ...);&lt;br /&gt;   ....&lt;br /&gt;   HANDLE hThread2 = CreateThread(..., (LPTHREAD_START_ROUTINE)function2, ...);&lt;br /&gt;   ....&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;Here is the same code ported to GNU/Linux.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;int x;&lt;br /&gt;pthread_mutex_t  hMutex;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;void *function1( void *Context) &lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   pthread_mutex_lock(&amp;hMutex);&lt;br /&gt;   x= 5;&lt;br /&gt;   pthread_mutex_unlock(&amp;hMutex);&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void *funtion2( void *Context) &lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   pthread_mutex_lock(&amp;hMutex);&lt;br /&gt;   x = 12;&lt;br /&gt;   pthread_mutex_unlock(&amp;hMutex);&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int WINAPI WinMain(...) &lt;br /&gt;{&lt;br /&gt;   pthread_mutexattr_t mAttr;&lt;br /&gt;   pthread_t hThread1;&lt;br /&gt;   pthread_t hThread2;&lt;br /&gt;&lt;br /&gt;   pthread:mutexattr_init(&amp;mAttr);&lt;br /&gt;   pthread_mutexattr_settype(&amp;mAttr, PTHREAD_MUTEX_RECURSIVE);&lt;br /&gt;   pthread_mutex_init(&amp;hMutex, &amp;mAttr);&lt;br /&gt;   ....&lt;br /&gt;   pthread_create(&amp;hThread1, NULL, function1, 0);&lt;br /&gt;   ....&lt;br /&gt;   pthread_create(&amp;hThread2, NULL, function2, 0);&lt;br /&gt;   ....&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;I am going to assume that you are familar with &lt;span class='notranslate'&gt;POSIX&lt;/span&gt; threads and thus the above code snippet should be fairly self-explanatory.&amp;nbsp; When dealing with a mutex, &lt;i&gt;WaitForSingleObject&lt;/i&gt; with no timeout is functionally equivalant to &lt;i&gt;pthread_mutex_lock&lt;/i&gt;.&amp;nbsp; The only thing of note is that you should probably use a recursive mutex since a Window thread can relock a mutex without first unlocking it.&lt;br /&gt;&lt;br /&gt;If the second parameter in &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; is 0 and not &lt;span class='notranslate'&gt;INFINITE&lt;/span&gt;, you should probably use &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_trylock&lt;/i&gt;&lt;/span&gt; instead of &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_lock&lt;/i&gt;&lt;/span&gt; since &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; does not enter a wait state if the mutex is not, to use Microsoft's term, &lt;span class='notranslate'&gt;&lt;i&gt;signaled&lt;/i&gt;&lt;/span&gt;; it always returns immediately.&lt;br /&gt;&lt;br /&gt;If the second parameter in &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; is neither 0 or &lt;span class='notranslate'&gt;INFINITE&lt;/span&gt;, you should probably use &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_timedlock&lt;/i&gt;&lt;/span&gt; instead of &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_lock&lt;/i&gt;&lt;/span&gt;. Under Windows the time-out interval is in milliseconds.&amp;nbsp; Under GNU/Linux you must pass a populated &lt;span class='notranslate'&gt;&lt;i&gt;timespec&lt;/i&gt;&lt;/span&gt; structure to &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_timedlock&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; Another wrinkle is that the interval clock and thus the clock resolution may or may not be based on the &lt;span class='notranslate'&gt;CLOCK_REALTIME&lt;/span&gt; clock depending on whether the &lt;span class='notranslate'&gt;Timers&lt;/span&gt; option is supported or not.&amp;nbsp; Therefore care needs to be taken to ensure that the time interval is correctly converted.&lt;br /&gt;&lt;br /&gt;The second wrinkle is that &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_timedlock&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;pthread_mutex_trylock&lt;/i&gt;&lt;/span&gt; do not work with recursive mutexes which are locked by the same thread as shown by the following example.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;time.h&amp;gt;&lt;br /&gt;#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main(int  argc,&lt;br /&gt;     char *argv)&lt;br /&gt;{&lt;br /&gt;    pthread_mutex_t hMutex1;&lt;br /&gt;    pthread_mutex_t hMutex2 = PTHREAD_MUTEX_INITIALIZER;&lt;br /&gt;    pthread_mutexattr_t mAttr;&lt;br /&gt;    struct timespec abstime;&lt;br /&gt;    int rc;&lt;br /&gt;&lt;br /&gt;    pthread_mutexattr_init(&amp;mAttr);&lt;br /&gt;    pthread_mutexattr_settype(&amp;mAttr, PTHREAD_MUTEX_RECURSIVE_NP);&lt;br /&gt;    pthread_mutex_init(&amp;hMutex1, &amp;mAttr);&lt;br /&gt;&lt;br /&gt;    /* lock the mutexes */&lt;br /&gt;    pthread_mutex_lock(&amp;hMutex1);&lt;br /&gt;    pthread_mutex_lock(&amp;hMutex2);&lt;br /&gt;&lt;br /&gt;    /* set absolute time to now + 5 seconds */&lt;br /&gt;    clock_gettime(CLOCK_REALTIME, &amp;abstime);&lt;br /&gt;    abstime.tv_sec += 5;&lt;br /&gt;&lt;br /&gt;    /* try to relock the first mutex */&lt;br /&gt;    if ((rc = pthread_mutex_timedlock(&amp;hMutex1, &amp;abstime)) &gt; 0 ) {&lt;br /&gt;        fprintf(stderr, "ERROR first pthread_mutex_timedlock. %s\n", strerror(rc));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /* set absolute time to now + 5 seconds */&lt;br /&gt;    clock_gettime(CLOCK_REALTIME, &amp;abstime);&lt;br /&gt;    abstime.tv_sec += 5;&lt;br /&gt;&lt;br /&gt;    /* try to relock the second mutex */&lt;br /&gt;    if ((rc = pthread_mutex_timedlock(&amp;hMutex2, &amp;abstime)) &gt; 0 ) {&lt;br /&gt;        fprintf(stderr, "ERROR second pthread_mutex_timedlock. %s\n", strerror(rc));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    exit(EXIT_SUCCESS);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;The only way around this problem is to either use non-recursive mutexes or ensure that threads do not attempt to relock recursive mutexes.&amp;nbsp;  In my experience &lt;span class='notranslate'&gt;Windows&lt;/span&gt; programmers tend to be rather loose and free in this respect so careful code inspection is usually required.&lt;br /&gt;&lt;br /&gt;Well that is all for now about the use of &lt;span class='notranslate'&gt;&lt;i&gt;WaitForSingleObject&lt;/i&gt;&lt;/span&gt; with mutexes.&amp;nbsp See my next post for ideas on how to port code which uses this &lt;span class='notranslate'&gt;API&lt;/span&gt; to handle  events.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-4805605294690404253?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/4805605294690404253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/04/porting-waitforsingleobject-to-gnulinux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/4805605294690404253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/4805605294690404253'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/04/porting-waitforsingleobject-to-gnulinux.html' title='Porting WaitForSingleObject to Linux - Part 1'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-4951962911417185795</id><published>2009-03-28T13:50:00.060-04:00</published><updated>2009-04-30T15:54:24.668-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xinerama'/><category scheme='http://www.blogger.com/atom/ns#' term='NVIDIA'/><category scheme='http://www.blogger.com/atom/ns#' term='Fedora'/><category scheme='http://www.blogger.com/atom/ns#' term='TwinView'/><category scheme='http://www.blogger.com/atom/ns#' term='GPU'/><title type='text'>Fedora 10 Dual Head Graphics Card</title><content type='html'>This post details how to install and configure two monitors on a single &lt;span class="notranslate"&gt;&lt;a href="http://www.evga.com/products/moreInfo.asp?pn=01G-P3-N959-TR&amp;amp;family=GeForce%209%20Series%20Family"&gt;EVGA GeForce 9500 GT&lt;/a&gt;&lt;/span&gt; graphics (video) card under &lt;span class="notranslate"&gt;Fedora 10&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;When I was researching dual head graphics cards for use with &lt;span class="notranslate"&gt;Fedora&lt;/span&gt;, I came across a lot of forum and blog entries on the subject but most of them contained obsolete or incorrect information - especially about &lt;span class="notranslate"&gt;&lt;a href="http://www.nvidia.com/object/feature_twinview.html"&gt;TwinView&lt;/a&gt;&lt;/span&gt;, &lt;span class="notranslate"&gt;&lt;a href="http://www.blogger.com/%20http://en.wikipedia.org/wiki/Xinerama"&gt;Xinerama&lt;/a&gt;&lt;/span&gt; and the &lt;span class="notranslate"&gt;&lt;a href="http://en.wikipedia.org/wiki/X_Window_System"&gt;X Window System&lt;/a&gt;&lt;/span&gt; configuration file.  Hopefully this post will provide readers with some useful up-to-date information on the subject.&lt;br /&gt;&lt;br /&gt;This particular graphics card &lt;span class="notranslate"&gt;(EVGA P/N 01G-P3-N959-TR)&lt;/span&gt; was of interest to me for a number of reasons but primarly because the card contains two heads each with &lt;span class="notranslate"&gt;&lt;a href="http://en.wikipedia.org/wiki/Digital_Visual_Interface"&gt;DVI-I&lt;/a&gt;&lt;/span&gt; connectors which would allow me to move away from VGA cabling altogether since my two HP w1907 19" LCD monitors also have DVI-I connectors.  In addition two heads on one graphics card enabled me to free up a &lt;span class="notranslate"&gt;PCI&lt;/span&gt; slot by eliminating the need for a second graphics card in my workstation.&lt;br /&gt;&lt;br /&gt;Using &lt;span class="notranslate"&gt;&lt;i&gt;TwinView&lt;/i&gt;&lt;/span&gt; was also of interest to me because it uses a single X screen, i.e. the driver conceals all information about the two separate monitors from the X server, and both monitors share the same frame buffer.  This means that I can continue to use functionality such as accelerated OpenGL without a problem.&lt;br /&gt;&lt;br /&gt;There are many graphics cards available which contain the &lt;span class="notranslate"&gt;&lt;a href="http://www.nvidia.com/object/product_geforce_9500gt_us.html"&gt;nVidia 9500GT&lt;/a&gt;&lt;/span&gt; &lt;span class="notranslate"&gt;&lt;a href="http://en.wikipedia.org/wiki/Graphics_processing_unit"&gt;GPU&lt;/a&gt;&lt;/span&gt; but, to date, few of these cards come with dual &lt;span class="notranslate"&gt;DVI-I&lt;/span&gt; heads. In addition &lt;span class="notranslate"&gt;nVidia&lt;/span&gt; fully supports their graphics cards on &lt;span class="notranslate"&gt;GNU/Linux&lt;/span&gt; and &lt;span class="notranslate"&gt;Solaris&lt;/span&gt; platforms.  Another feature of modern &lt;span class="notranslate"&gt;nVidia GPUs&lt;/span&gt; which is of great interest to me is their support for the &lt;span class="notranslate"&gt;&lt;a href="http://en.wikipedia.org/wiki/CUDA"&gt;CUDA (Compute Unified Device Architecture)&lt;/a&gt;&lt;/span&gt; architecture which I wish to experiment with a part of a project which I am currently working on for a customer.&lt;br /&gt;&lt;br /&gt;You can use a single monitor with this card &lt;span class="notranslate"&gt;out-of-the-box&lt;/span&gt; using the default &lt;i&gt;nv&lt;/i&gt; driver which comes standard with Fedora.  However, to use two monitors with this card, you need to download and install the correct package for your &lt;i&gt;specific&lt;/i&gt; kernel, i.e.&lt;span class="notranslate"&gt;&lt;i&gt;&lt;br /&gt;kmod-nvidia-2.6.27.19-170.2.35.fc10.x86_64-180.29-1.fc10.1.x86_64&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;in my particular case as my present kernel is &lt;span class="notranslate"&gt;&lt;i&gt;2.6.27.19-170.2.35&lt;/i&gt;&lt;/span&gt;.  Selecting this package will cause three other packages to be also downloaded and installed on your system unless they already exist.  These packages are &lt;span class="notranslate"&gt;&lt;i&gt;livna-config-display-*&lt;/i&gt;&lt;/span&gt;, &lt;span class="notranslate"&gt;&lt;i&gt;xorg-x11-drv-nvidia-*&lt;/i&gt;&lt;/span&gt;, and &lt;span class="notranslate"&gt;&lt;i&gt;xorg-x11-drv-nvidia-libs-*&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;These packages not not available in the regular &lt;span class="notranslate"&gt;Fedora&lt;/span&gt; repositories.  You need to add the &lt;span class="notranslate"&gt;&lt;i&gt;rpmfusion&lt;/i&gt;&lt;/span&gt; repositories to &lt;span class="notranslate"&gt;&lt;i&gt;/etc/yum.conf&lt;/i&gt;&lt;/span&gt; or to the &lt;span class="notranslate"&gt;&lt;i&gt;/etc/yum.repos.d&lt;/i&gt;&lt;span&gt; subdirectory.  Here is one way of installed the repository configuration files into &lt;span class="notranslate"&gt;&lt;i&gt;/etc/yum.repos.d&lt;/i&gt;&lt;span&gt;.&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;rpm -ivh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm&lt;br /&gt;rpm -ivh http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm&lt;br /&gt;rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-rpmfusion-*&lt;/pre&gt;&lt;/div&gt;Before you actually download these packages, make a copy of your &lt;span class="notranslate"&gt;X Server&lt;/span&gt; configuration file i.e. &lt;span class="notranslate"&gt;&lt;i&gt;/etc/X11/xorg.conf&lt;/i&gt;&lt;/span&gt; if one exists.  On &lt;span class="notranslate"&gt;Fedora 10&lt;/span&gt;, it may not if you have a very simple setup.  Don't say that you were not warned!&lt;br /&gt;&lt;br /&gt;You then should reboot your system and use the nVidia configuration utility either from the command line (&lt;span class="notranslate"&gt;&lt;i&gt;/usr/bin/nvidia-settings&lt;/i&gt;&lt;/span&gt;) or via the &lt;span class="notranslate"&gt;&lt;i&gt;/Applications/System Tools/nVidia Display Settings&lt;/i&gt;&lt;/span&gt; menu option to configure the dual monitor setup.&lt;br /&gt;&lt;br /&gt;The following is a screenshot of the nVidia configuration utility after invocation.&lt;span class="notranslate"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_IrJjVkDo0pg/Sc52CTrKxQI/AAAAAAAAAFU/4y2-2FZJxTk/s1600-h/nvidia1"&gt;&lt;img style="cursor: pointer; width: 417px; height: 290px;" src="http://4.bp.blogspot.com/_IrJjVkDo0pg/Sc52CTrKxQI/AAAAAAAAAFU/4y2-2FZJxTk/s320/nvidia1" alt="" id="BLOGGER_PHOTO_ID_5318317991984284930" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;and here is a screenshot of the utility showing the &lt;span class="notranslate"&gt;X Server display Configuration&lt;/span&gt; panel.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_IrJjVkDo0pg/Sc52CsI4SxI/AAAAAAAAAFc/JuAitui7B44/s1600-h/nvidia2.png"&gt;&lt;img style="cursor: pointer; width: 417px; height: 445px;" src="http://3.bp.blogspot.com/_IrJjVkDo0pg/Sc52CsI4SxI/AAAAAAAAAFc/JuAitui7B44/s320/nvidia2.png" alt="" id="BLOGGER_PHOTO_ID_5318317998551354130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are limits to how you can configure your setup.  You can have only one virtual screen per graphics card.  Thus &lt;span class="notranslate"&gt;&lt;i&gt;zaphod mode&lt;/i&gt;&lt;/span&gt;, i.e. the ability to assign each monitor on a device to a different screen, is not supported nor can you combine monitors from multiple graphic cards into a single screen.&lt;br /&gt;&lt;br /&gt;Unless you modify your &lt;span class="notranslate"&gt;X Server&lt;/span&gt; configuration file all settings will be lost upon the next reboot or restart of the &lt;span class="notranslate"&gt;X Server&lt;/span&gt;.  For this reason the utility has options to create a new &lt;span class="notranslate"&gt;X Server&lt;/span&gt; configuration file (in my case &lt;span class="notranslate"&gt;&lt;i&gt;/etc/X11/xorg.conf&lt;/i&gt;&lt;/span&gt;) or to merge with your existing configuration file.&lt;br /&gt;&lt;br /&gt;For completeness, here is a copy of the &lt;span class="notranslate"&gt;&lt;i&gt;/etc/X11/xorg.conf&lt;/i&gt;&lt;/span&gt; which I currently use with this configuration.&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;#&lt;br /&gt;# FPMurphy 3/28/2009 Twinview EVGA 9500 GT&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;Section "ServerLayout"&lt;br /&gt;Identifier    "Layout0"&lt;br /&gt;Screen    0   "Screen0" 0 0&lt;br /&gt;InputDevice   "Keyboard0" "CoreKeyboard"&lt;br /&gt;InputDevice   "Mouse0" "CorePointer"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Files"&lt;br /&gt;FontPath      "/usr/share/fonts/default/Type1"&lt;br /&gt;ModulePath    "/usr/lib64/xorg/modules/extensions/nvidia"&lt;br /&gt;ModulePath    "/usr/lib64/xorg/modules"&lt;br /&gt;&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Module"&lt;br /&gt;Load          "dbe"&lt;br /&gt;Load          "extmod"&lt;br /&gt;Load          "type1"&lt;br /&gt;Load          "freetype"&lt;br /&gt;Load          "glx"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "ServerFlags"&lt;br /&gt;Option        "Xinerama" "0"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt;Identifier     "Mouse0"&lt;br /&gt;Driver         "mouse"&lt;br /&gt;Option         "Protocol" "auto"&lt;br /&gt;Option         "Device" "/dev/input/mice"&lt;br /&gt;Option         "ZAxisMapping" "4 5 6 7"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt;Identifier     "Keyboard0"&lt;br /&gt;Driver         "kbd"&lt;br /&gt;Option         "XkbLayout" "us"&lt;br /&gt;Option         "XkbModel" "pc105"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Monitor"&lt;br /&gt;Identifier     "Monitor0"&lt;br /&gt;VendorName     "HP"&lt;br /&gt;ModelName      "w1907"&lt;br /&gt;HorizSync       24.0 - 83.0&lt;br /&gt;VertRefresh     50.0 - 76.0&lt;br /&gt;Option         "DPMS"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Device"&lt;br /&gt;Identifier     "Device0"&lt;br /&gt;Driver         "nvidia"&lt;br /&gt;VendorName     "NVIDIA Corporation"&lt;br /&gt;BoardName      "GeForce 9500 GT"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Screen"&lt;br /&gt;Identifier     "Screen0"&lt;br /&gt;Device         "Device0"&lt;br /&gt;Monitor        "Monitor0"&lt;br /&gt;DefaultDepth    24&lt;br /&gt;Option         "TwinView" "1"&lt;br /&gt;Option         "TwinViewXineramaInfoOrder" "DFP-1"&lt;br /&gt;Option         "metamodes" "DFP-0: nvidia-auto-select +1440+0, DFP-1: nvidia-auto-select +0+0"&lt;br /&gt;SubSection     "Display"&lt;br /&gt;   Depth       24&lt;br /&gt;EndSubSection&lt;br /&gt;EndSection&lt;/pre&gt;&lt;/div&gt;If the nVidia GLX module loaded correctly, you should able to run &lt;span class="notranslate"&gt;&lt;i&gt;/usr/bin/glxgears&lt;/i&gt;&lt;/span&gt; successfully.  If it fails to run, check your &lt;span class="notranslate"&gt;&lt;i&gt;/var/log/Xorg.O.log&lt;/i&gt;&lt;/span&gt; file to see if the &lt;span class="notranslate"&gt;nVidia &lt;i&gt;libglx&lt;/i&gt;&lt;/span&gt; library is being loaded or not.  You should see something like the following&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;(II) Loading /usr/lib64/xorg/modules/extensions/nvidia//libglx.so&lt;br /&gt;(II) Module glx: vendor="NVIDIA Corporation"&lt;br /&gt;      compiled for 4.0.2, module version = 1.0.0&lt;br /&gt;      Module class: X.Org Server Extension&lt;br /&gt;(II) NVIDIA GLX Module  173.14.18  Mon Mar  2 15:55:02 PST 2009&lt;br /&gt;(II) Loading extension GLX&lt;/pre&gt;&lt;/div&gt;If you do not see that specific path for the &lt;span class="notranslate"&gt;nVidia &lt;i&gt;libglx.so&lt;/i&gt;&lt;/span&gt; you need to go back and fix up the &lt;span class="notranslate"&gt;&lt;i&gt;ModulePath&lt;/i&gt;&lt;/span&gt; lines in your &lt;span class="notranslate"&gt;&lt;i&gt;xorg.conf&lt;/i&gt;&lt;/span&gt;.  Note that the order of the &lt;span class="notranslate"&gt;&lt;i&gt;ModulePath&lt;/i&gt;&lt;/span&gt; lines is important as each path is searched in turn from first to last.&lt;br /&gt;&lt;br /&gt;With this configuration the output from the &lt;span class="notranslate"&gt;&lt;i&gt;xrandr&lt;/i&gt;&lt;/span&gt; utility should be something to this:&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;#xrandr -q&lt;br /&gt;Screen 0: minimum 2880 x 900, current 2880 x 900, maximum 2880 x 900&lt;br /&gt;default connected 2880x900+0+0 0mm x 0mm&lt;br /&gt; 2880x900       50.0*&lt;br /&gt;#&lt;/pre&gt;&lt;/div&gt;If you are unfamiliar with &lt;span class="notranslate"&gt;&lt;i&gt;xrandr&lt;/i&gt;&lt;/span&gt; which is the command line interface to the &lt;span class="notranslate"&gt;X Server &lt;a href="http://en.wikipedia.org/wiki/XRandR"&gt;RandR&lt;/a&gt;&lt;/span&gt; extension, I recommend that you become familar with it as it is one of the more useful extensions in the &lt;span class="notranslate"&gt;X Window System&lt;/span&gt; when you have more than one head on a graphics card.&lt;br /&gt;&lt;br /&gt;The following is a list of the &lt;span class="notranslate"&gt;nvidia&lt;/span&gt;-related kernel modules.&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;# modprobe -l | grep nvidia&lt;br /&gt;/lib/modules/2.6.27.19-170.2.35.fc10.x86_64/extra/nvidia/nvidia.ko&lt;br /&gt;/lib/modules/2.6.27.19-170.2.35.fc10.x86_64/kernel/drivers/video/nvidia/nvidiafb.ko&lt;br /&gt;/lib/modules/2.6.27.19-170.2.35.fc10.x86_64/kernel/drivers/video/backlight/mbp_nvidia_bl.ko&lt;br /&gt;# lsmod | grep nv&lt;br /&gt;nvidia               8117992  20&lt;br /&gt;i2c_core               29216  2 nvidia,i2c_i801&lt;br /&gt;#&lt;/pre&gt;&lt;/div&gt;One thing to watch out for is the &lt;span class="notranslate"&gt;&lt;i&gt;nvidia&lt;/i&gt;&lt;/span&gt; system service can change your &lt;span class="notranslate"&gt;&lt;i&gt;/etc/X11/xorg.conf&lt;/i&gt;&lt;/span&gt; file without informing you.  To eliminate this possibility, I strongly recommend that you turn the service off.&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;# chkconfig --list  nvidia&lt;br /&gt;nvidia          0:off 1:off 2:on 3:on 4:on 5:on 6:off&lt;br /&gt;# chkconfig nvidia off&lt;br /&gt;#&lt;/pre&gt;&lt;/div&gt;Note that these instructions may not apply to&lt;span class="notranslate"&gt; Fedora 11&lt;/span&gt; (aka &lt;span class="notranslate"&gt;&lt;i&gt;Leonidas&lt;/i&gt;&lt;/span&gt;) as it is getting a new default driver for &lt;span class="notranslate"&gt;nVidia&lt;/span&gt; grahics chipsets called &lt;span class="notranslate"&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt;. The &lt;span class="notranslate"&gt;&lt;i&gt;nv&lt;/i&gt;&lt;/span&gt; driver will still be installed by default and will be used as a fall-back where &lt;span class="notranslate"&gt;&lt;i&gt;nouveau&lt;/i&gt;&lt;/span&gt; fails to work for whatever reason.&lt;br /&gt;&lt;br /&gt;Because the &lt;span class="notranslate"&gt;nVidia&lt;/span&gt; kernel module is built specifically for each kernel release, you need to download and install a new &lt;span class="notranslate"&gt;nVidia&lt;/span&gt; kernel module each time your kernel is updated.&amp;nbsp; If you suddenly are confronted with a non-responsive blank screen after a reboot, this is probably what has happened.&amp;nbsp; The easiest fix in this case is to log in to one of the virtual consoles, downgrade the system to runlevel 2, remove the old &lt;span class="notranslate"&gt;&lt;i&gt;kmod-nvidia-173*&lt;/i&gt;&lt;/span&gt; package, and install the new &lt;span class="notranslate"&gt;&lt;i&gt;kmod-nvidia-173*&lt;/i&gt;&lt;/span&gt;&lt;span class="notranslate"&gt; package followed by a reboot.&lt;br /&gt;&lt;br /&gt;[ Updated Apr 28 2009] Alternatively you can let your system always automatically download and install the latest &lt;span class="notranslate"&gt;nVidia&lt;/span&gt; kernel module whenever a new kernel is downloaded by simply installing a meta-package called &lt;span class="notranslate"&gt;&lt;i&gt;kmod-nvidia-173xx-173.14.18-1.fc10.1.x86_64&lt;/i&gt;&lt;/span&gt; instead of the kernel specific package.&lt;span class='notranslate'&gt;  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_IrJjVkDo0pg/SfoAwws5IrI/AAAAAAAAAFk/CrMlsbC5WeY/s1600-h/1"&gt;&lt;img style="cursor: pointer; width: 417px; height: 290px;" src="http://1.bp.blogspot.com/_IrJjVkDo0pg/SfoAwws5IrI/AAAAAAAAAFk/CrMlsbC5WeY/s320/1" alt="" id="BLOGGER_PHOTO_ID_5330573946653319858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Here is the relevant portion of &lt;span class="notranslate"&gt;&lt;i&gt;/var/log/yum.log&lt;/i&gt;&lt;/span&gt; which shows the packages which were installed as a result of installing this meta-package&lt;div class="notranslate"&gt;&lt;pre class="displaybox"&gt;Apr 23 15:36:59 Installed: system-config-display-1.1.1-1.fc10.noarch&lt;br /&gt;Apr 23 15:36:59 Installed: livna-config-display-0.0.22-1.fc10.noarch&lt;br /&gt;Apr 23 15:37:00 Installed: xorg-x11-drv-nvidia-173xx-libs-173.14.18-1.fc10.x86_64&lt;br /&gt;Apr 23 15:37:06 Installed: xorg-x11-drv-nvidia-173xx-173.14.18-1.fc10.x86_64&lt;br /&gt;Apr 23 15:37:09 Installed: kmod-nvidia-173xx-2.6.27.21-170.2.56.fc10.x86_64-173.14.18-1.fc10.1.x86_64&lt;br /&gt;Apr 23 15:37:09 Installed: kmod-nvidia-173xx-173.14.18-1.fc10.1.x86_64&lt;/pre&gt;&lt;/div&gt;As usual, I hope that this information has been of help to you.  If you are a software developer, I strongly encourage you to upgrade to a dual head system as studies have consistently shown that your productivity can increase by as much as 20% with such a configuration.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-4951962911417185795?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/4951962911417185795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/03/fedora-10-dual-head-graphics-card.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/4951962911417185795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/4951962911417185795'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/03/fedora-10-dual-head-graphics-card.html' title='Fedora 10 Dual Head Graphics Card'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_IrJjVkDo0pg/Sc52CTrKxQI/AAAAAAAAAFU/4y2-2FZJxTk/s72-c/nvidia1' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-4311221163612904455</id><published>2009-03-14T21:00:00.009-04:00</published><updated>2009-03-16T09:43:11.956-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CDROM'/><category scheme='http://www.blogger.com/atom/ns#' term='bootable'/><category scheme='http://www.blogger.com/atom/ns#' term='ksh93'/><category scheme='http://www.blogger.com/atom/ns#' term='shell script'/><title type='text'>Bootable DVD/CDROM</title><content type='html'>Have you ever wanted to determine whether a DVD or CDROM is a bootable CDROM or DVD from within a shell script?&amp;nbsp; If you use &lt;span class='notranslate'&gt;GNU/Linux&lt;/span&gt; you could parse the output from the &lt;span class='notranslate'&gt;&lt;i&gt;isoinfo&lt;/i&gt;&lt;/span&gt; utility which is part of the &lt;span class='notranslate'&gt;&lt;a href="http://cdrecord.berlios.de/private/cdrecord.html"&gt;CDRecord&lt;/a&gt;&lt;/span&gt; tools suite.&lt;br /&gt;&lt;br /&gt;What if the &lt;span class='notranslate'&gt;&lt;i&gt;isoinfo&lt;/i&gt;&lt;/span&gt; utility is not available on your operating system?&amp;nbsp; In this case you have to resort to rolling you own compiled langauge utility or shell script.&amp;nbsp; To do this you need to understand where to find the specific bytes on a CDROM/DVD which indicate whether it is a bootable CDROM/DVD or not.&amp;nbsp; The relevant specification covering bootable CDROMs (and by extension bootable DVDs) is the &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/El_Torito_(CD-ROM_standard)"&gt;El Torito&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; specification which is an extension to the &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://en.wikipedia.org/wiki/ISO_9660'&gt;ISO 9660&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; specification. &lt;br /&gt;&lt;br /&gt;Our first shell script uses the &lt;span class='notranslate'&gt;&lt;i&gt;dd&lt;/i&gt;&lt;/span&gt; utility to read in the required bytes which are then sliced and diced using the &lt;span class='notranslate'&gt;&lt;i&gt;xxd&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;cut&lt;/i&gt;&lt;/span&gt; utilities..&amp;nbsp; Sector 17 (hexadecimal 11, the &lt;span class='notranslate'&gt;&lt;i&gt;Boot Record Volume&lt;/i&gt;&lt;/span&gt;) contains two bytes at a specific offset which are an absolute pointer to the &lt;span class='notranslate'&gt;&lt;i&gt;Booting Catalog&lt;/i&gt;&lt;/span&gt; which in turn contains a specific byte which indicates whether a CDROM/DVD is bootable or not.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#!/bin/bash&lt;br /&gt;#&lt;br /&gt;# use dd to read in the required bytes&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;DEVICE="/dev/sr0"&lt;br /&gt;VERBOSE=1&lt;br /&gt;&lt;br /&gt;# get 2 bytes at absolute offset 34887&lt;br /&gt;bchex=`dd if=${DEVICE} skip=$(( 0x800 * 0x11 + 0x47))  bs=1 count=2 conv=swab 2&gt;/dev/null | xxd | cut -d" " -f2`&lt;br /&gt;&lt;br /&gt;# get one byte&lt;br /&gt;bcdec=`printf "%d" 0x${bchex}`&lt;br /&gt;bootable=`dd if=${DEVICE}  bs=1 skip=$(( 0x800 * bcdec + 0x20))  count=1  2&gt;/dev/null | xxd | cut -d" " -f2`&lt;br /&gt;&lt;br /&gt;if [[ $bootable = 88 ]]; then&lt;br /&gt;   [ $VERBOSE ] &amp;&amp; printf "Bootable CDROM\n"&lt;br /&gt;   exit 0&lt;br /&gt;else&lt;br /&gt;   [ $VERBOSE ] &amp;&amp; printf "Not a bootable CDROM\n"&lt;br /&gt;   exit 1&lt;br /&gt;fi&lt;/pre&gt;&lt;/div&gt;The previous shell script is classical in its approach to the problem in that it uses a number of small specialized utilities to achieve the desired result.&lt;br /&gt;&lt;br /&gt;Another way of achieving the same result is to use the extended I/O features of &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; as shown in the following shell script.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#!/bin/ksh93&lt;br /&gt;#&lt;br /&gt;# Cannot open DVD/CDROM for read/write - hence cannot seek &lt;br /&gt;# forward on file descriptor. Workaround is to close and &lt;br /&gt;# reopen the file descriptor.&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;DEVICE="/dev/sr0"&lt;br /&gt;VERBOSE=1&lt;br /&gt;&lt;br /&gt;# read 2 bytes&lt;br /&gt;redirect 3&lt; $DEVICE || exit 3&lt;br /&gt;3&lt;#(( 0x800 * 0x11 + 0x47 ))&lt;br /&gt;read -u3 -N 1 bchex1&lt;br /&gt;read -u3 -N 1 bchex2&lt;br /&gt;redirect 3&lt;&amp;-&lt;br /&gt;&lt;br /&gt;# calculate absolute offset&lt;br /&gt;integer bcdec=$(printf "%d" 0x$(printf "%x%x\n"  "'$bchex2" "'$bchex1"))&lt;br /&gt;&lt;br /&gt;# read 1 byte&lt;br /&gt;redirect 3&lt; $DEVICE || exit 3&lt;br /&gt;3&lt;#(( 0x800 * bcdec + 0x20 ))&lt;br /&gt;read -u3 -N 1 bootable&lt;br /&gt;redirect 3&lt;&amp;-&lt;br /&gt;&lt;br /&gt;if [[ $(printf "%x" "'$bootable") = 88 ]]; then&lt;br /&gt;   [ $VERBOSE ] &amp;&amp; printf "Bootable CDROM\n"&lt;br /&gt;   exit 0&lt;br /&gt;else&lt;br /&gt;   [ $VERBOSE ] &amp;&amp; printf "Not a bootable CDROM\n"&lt;br /&gt;   exit 1&lt;br /&gt;fi&lt;/pre&gt;&lt;/div&gt;The advantage of this approach is that all operations are done within the existing shell process without the overhead of &lt;span class='notranslate'&gt;&lt;i&gt;fork/execs&lt;/i&gt;&lt;/span&gt; to invoke external utilities such as &lt;span class='notranslate'&gt;&lt;i&gt;dd&lt;/i&gt;&lt;/span&gt; etc.&lt;br /&gt;&lt;br /&gt;Note that both of the above shell scripts assume that the CDROM or DVD being checked is either non-bootable or contains a single boot-image configuration.&amp;nbsp; They can easily be extended to check for a multiple boot-image configuration.&amp;nbsp; That is left as an exercise for you the reader.&lt;br /&gt;&lt;br /&gt;For the record, these two shell scripts were tested on &lt;span class='notranslate'&gt;Fedora 10&lt;/span&gt; using version &lt;span class='notranslate'&gt;&lt;i&gt;M&lt;/i&gt;&lt;/span&gt; of &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-4311221163612904455?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/4311221163612904455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/03/bootable-dvdcdrom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/4311221163612904455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/4311221163612904455'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/03/bootable-dvdcdrom.html' title='Bootable DVD/CDROM'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-8844041782392446446</id><published>2009-02-20T19:54:00.050-05:00</published><updated>2009-02-23T08:53:37.157-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit manipulation'/><category scheme='http://www.blogger.com/atom/ns#' term='ksh93'/><category scheme='http://www.blogger.com/atom/ns#' term='Shell'/><title type='text'>KSH93 Bit Manipulation</title><content type='html'>When programmers think about bitwise manipulation, they usually think about using C or C++ to solve their problem since both programming languages provide a rich set of features which make it easy to perform bitwise manipulation.&lt;br /&gt;&lt;br /&gt;However it is possible to just as easily perform such operations using the &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; shell.&amp;nbsp; This post will explain what bitwise manipulation and number conversion facilities are available in &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; and provide some hopefully useful utilities and examples.&lt;br /&gt;&lt;br /&gt;Many programmers are unaware that &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; has builtin support for different &lt;a href='http://en.wikipedia.org/wiki/Radix'&gt;numeral radices&lt;/a&gt; (AKA arithmetic bases) as shown in the following example.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ print $(( 10 + 20 ))&lt;br /&gt;30&lt;br /&gt;$ print $(( 2#10 + 20 ))&lt;br /&gt;22&lt;br /&gt;$ print $(( 2#10 + 4#20 ))&lt;br /&gt;10&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;where base 2 is denoted by &lt;i&gt;2#&lt;/i&gt;, base 4 by &lt;i&gt;#4&lt;/i&gt; and so on.&amp;nbsp; The general case syntax is &lt;i&gt;[base#]n&lt;/i&gt; where &lt;i&gt;base&lt;/i&gt; is a decimal number between 2 and 36 representing the arithmetic base and &lt;i&gt;n&lt;/i&gt; is a number in that &lt;i&gt;base&lt;/i&gt;.&amp;nbsp; You can mix and match bases within expressions.&amp;nbsp; As you would expect, the default base, i.e. if &lt;i&gt;[base#]&lt;/i&gt; is omitted, is decimal(10).&lt;br /&gt;&lt;br /&gt;Here is an example of how to convert decimal 255 to base 2, base 8 and base 16 respectively using the &lt;i&gt;typeset&lt;/i&gt; command.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ typeset -i2 a=255&lt;br /&gt;$ echo $a&lt;br /&gt;2#11111111&lt;br /&gt;$ typeset -i8 a=255&lt;br /&gt;$ echo $a&lt;br /&gt;8#377&lt;br /&gt;$ typeset -i16 a=255&lt;br /&gt;$ echo $a&lt;br /&gt;16#ff&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;Note that &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; displays the base prefix before each number unless it is a decimal number, i.e. base 10.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Bit_manipulation"&gt;bitwise manipulation&lt;/a&gt; operators in &lt;i&gt;ksh93&lt;/i&gt; are AND, OR, XOR, SHIFT LEFT and SHIFT RIGHT.&amp;nbsp; There are no SHIFT ROTATE or COMPLEMENT operators.&amp;nbsp; The following is the list of supported bitwise operators in decreasing order of precedence which, by the way, is the same as in the C programming language.&lt;br /&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;table&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;span class='notranslate'&gt;&lt;i&gt;&lt;&lt; &gt;&gt;&lt;/i&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Bitwise shift left, shift right&lt;td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;span class='notranslate'&gt;&lt;i&gt;&amp;&lt;/i&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Bitwise AND&lt;td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;span class='notranslate'&gt;&lt;i&gt;^&lt;/i&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Bitwise XOR&lt;td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;span class='notranslate'&gt;&lt;i&gt;|&lt;/i&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;Bitwise OR&lt;td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The following shell script includes both logical and bitwise operators together with the expected output for each statement.&amp;nbsp; Notice the difference in output between a logical and bitwise operator.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#!/bin/ksh93&lt;br /&gt;&lt;br /&gt;integer -i2 a=5&lt;br /&gt;integer -i2 b=6&lt;br /&gt;&lt;br /&gt;# expected output 1&lt;br /&gt;print $(( a &lt; b ))&lt;br /&gt;# expected output 0&lt;br /&gt;print $(( a &gt; b ))&lt;br /&gt;# expected output 3&lt;br /&gt;print $(( a ^ b ))&lt;br /&gt;# expected output 4&lt;br /&gt;print $(( a &amp; b ))&lt;br /&gt;# expected output 1&lt;br /&gt;print $(( a &amp;&amp; b ))&lt;br /&gt;# expected output 7&lt;br /&gt;print $(( a | b ))&lt;br /&gt;# expected output 1&lt;br /&gt;print $(( a || b ))&lt;/pre&gt;&lt;/div&gt;A useful feature of bitwise operators is that by using the shift left and shift right bitwise operators you can mimic multiplication or division by 2 or a power of 2.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ x=4&lt;br /&gt;$ print $((x &lt;&lt; 1))&lt;br /&gt;8&lt;br /&gt;$ print $(( x &lt;&lt; 2 ))&lt;br /&gt;16&lt;br /&gt;$ print $(( x &gt;&gt; 1 ))&lt;br /&gt;2&lt;br /&gt;$ print $(( x &gt;&gt; 2 ))&lt;br /&gt;1&lt;/pre&gt;&lt;/div&gt;Here is a fairly simple shell script which uses numeric base conversion and bitwise operators to calculate the network and broadcast addresses for a given &lt;span class='notranslate'&gt;IP&lt;/span&gt; address and subnet mask.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#!/bin/ksh93&lt;br /&gt;&lt;br /&gt;typeset -i2 mask=255&lt;br /&gt;&lt;br /&gt;[[ $# != 2 ]] &amp;&amp; {&lt;br /&gt;   echo "Usage: $0 ipaddress subnetmask"&lt;br /&gt;   exit 1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;SaveIFS=$IFS&lt;br /&gt;IFS=.&lt;br /&gt;typeset -a IParr=($1)&lt;br /&gt;typeset -a NMarr=($2)&lt;br /&gt;IFS=$SaveIFS&lt;br /&gt;&lt;br /&gt;typeset -i2 ip1=${IParr[0]}&lt;br /&gt;typeset -i2 ip2=${IParr[1]}&lt;br /&gt;typeset -i2 ip3=${IParr[2]}&lt;br /&gt;typeset -i2 ip4=${IParr[3]}&lt;br /&gt;&lt;br /&gt;typeset -i2 nm1=${NMarr[0]}&lt;br /&gt;typeset -i2 nm2=${NMarr[1]}&lt;br /&gt;typeset -i2 nm3=${NMarr[2]}&lt;br /&gt;typeset -i2 nm4=${NMarr[3]}&lt;br /&gt;&lt;br /&gt;echo&lt;br /&gt;echo "       IP Address: $1"&lt;br /&gt;echo "      Subnet Mask: $2"&lt;br /&gt;echo "  Network Address: $((ip1 &amp; nm1)).$((ip2 &amp; nm2)).$((ip3 &amp; nm3)).$((ip4 &amp; nm4))"&lt;br /&gt;echo "Broadcast Address: $((ip1 | (mask ^ nm1))).$((ip2 | (mask ^ nm2))).$((ip3 | (mask ^ nm3))).$(( ip4 | (mask ^ nm4)))"&lt;br /&gt;echo&lt;br /&gt;&lt;br /&gt;exit 0&lt;/pre&gt;&lt;/div&gt;Some sample output for this script.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ ./calculate-address 10.150.12.1 255.255.255.0&lt;br /&gt;&lt;br /&gt;       IP Address: 10.150.12.1&lt;br /&gt;      Subnet Mask: 255.255.255.0&lt;br /&gt;  Network Address: 10.150.12.0&lt;br /&gt;Broadcast Address: 10.150.12.255&lt;br /&gt;&lt;br /&gt;$ ./calculate-address 10.150.12.1 255.255.254.0&lt;br /&gt;&lt;br /&gt;       IP Address: 10.150.12.1&lt;br /&gt;      Subnet Mask: 255.255.254.0&lt;br /&gt;  Network Address: 10.150.12.0&lt;br /&gt;Broadcast Address: 10.150.13.255&lt;/pre&gt;&lt;/div&gt;The next example calculates the network and broadcast addresses for a &lt;span class='notranslate'&gt;&lt;a href='http://www.ietf.org/rfc/rfc1519.txt'&gt;Classless Inter-Domain Routing (CIDR)&lt;/a&gt;&lt;/span&gt; compliant &lt;span class='notranslate'&gt;IP&lt;/span&gt; address.&amp;nbsp; Note the use of the shift right operator in calculating the network mask.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#!/bin/ksh93&lt;br /&gt;&lt;br /&gt;[[ $# != 1 ]] &amp;&amp; {&lt;br /&gt;   echo "Usage: $0 ipaddress/netmask"&lt;br /&gt;   exit 1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;SaveIFS=$IFS&lt;br /&gt;IFS="./"&lt;br /&gt;typeset -a IParr=($1)&lt;br /&gt;IFS=$SaveIFS&lt;br /&gt;&lt;br /&gt;typeset -i2 ip1=${IParr[0]}&lt;br /&gt;typeset -i2 ip2=${IParr[1]}&lt;br /&gt;typeset -i2 ip3=${IParr[2]}&lt;br /&gt;typeset -i2 ip4=${IParr[3]}&lt;br /&gt;typeset -i2 cidr=${IParr[4]}&lt;br /&gt;&lt;br /&gt;typeset -i2 nm1=0 nm2=0 nm3=0 nm4=0&lt;br /&gt;&lt;br /&gt;typeset -i quad=$(( cidr / 8 ))&lt;br /&gt;sigbits=$(( cidr % 8 ))&lt;br /&gt;if (( sigbits != 0 )); then&lt;br /&gt;   slot=$(( 256 - ( 256 &gt;&gt; $sigbits ) ))&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;for (( i=1; i &lt; 5; i++ ))&lt;br /&gt;do&lt;br /&gt;   nameref nm=nm${i}&lt;br /&gt;   if (( quad != 0 )); then&lt;br /&gt;      nm=255&lt;br /&gt;      (( --quad ))&lt;br /&gt;   elif (( quad == 0 )); then&lt;br /&gt;      nm=slot&lt;br /&gt;      break&lt;br /&gt;   fi&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;typeset -i2 mask=255&lt;br /&gt;&lt;br /&gt;print&lt;br /&gt;print "           IP Address: $((ip1)).$((ip2)).$((ip3)).$((ip4))"&lt;br /&gt;print "    CIDR Netmask Mask: $((nm1)).$((nm2)).$((nm3)).$((nm4))"&lt;br /&gt;print " CIDR Network (Route): $((ip1 &amp; nm1)).$((ip2 &amp; nm2)).$((ip3 &amp; nm3)).$((ip4 &amp; nm4))"&lt;br /&gt;print "    Broadcast Address: $((ip1 | (mask ^ nm1))).$((ip2 | (mask ^ nm2))).$((ip3 | (mask ^ nm3))).$((ip4 | (mask ^ n&lt;br /&gt;m4)))"&lt;br /&gt;print&lt;br /&gt;&lt;br /&gt;exit 0&lt;/pre&gt;&lt;/div&gt;Sample output:&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ ./calculate-address "192.168.21.12/18"&lt;br /&gt;&lt;br /&gt;           IP Address: 192.168.21.12&lt;br /&gt;    CIDR Network Mask: 255.255.192.0&lt;br /&gt; CIDR Network (Route): 192.168.0.0&lt;br /&gt;    Broadcast Address: 192.168.63.255&lt;/pre&gt;&lt;/div&gt;While both the &lt;span class='notranslate'&gt;&lt;i&gt;bash&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;zsh&lt;/i&gt;&lt;/span&gt; shells also provide a full set of bitwise operators, only &lt;span class='notranslate'&gt;&lt;i&gt;ksh93&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;zsh&lt;/i&gt;&lt;/span&gt; with their builtin support for numeric base conversions makes such bitwise operators truly useful in shell scripts.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-8844041782392446446?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/8844041782392446446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/02/khs93-bit-manipulation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8844041782392446446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8844041782392446446'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/02/khs93-bit-manipulation.html' title='KSH93 Bit Manipulation'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-8522778169521719531</id><published>2009-02-15T11:05:00.032-05:00</published><updated>2009-09-01T15:23:22.071-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tomboy'/><category scheme='http://www.blogger.com/atom/ns#' term='D-Bus'/><category scheme='http://www.blogger.com/atom/ns#' term='Shell'/><title type='text'>Monitoring D-Bus</title><content type='html'>Because &lt;span class='notranslate'&gt;&lt;a href='http://www.freedesktop.org/wiki/Software/dbus'&gt;D-Bus&lt;/a&gt;&lt;/span&gt; operates for the most part under the hood invisible to the user, means of monitoring &lt;span class='notranslate'&gt;D-Bus&lt;/span&gt; messages is important for both activation and debugging purposes.&amp;nbsp; In this post I examine how to monitor and act on such messages.&amp;nbsp; I assume that you are relatively familiar with &lt;span class='notranslate'&gt;D-Bus&lt;/span&gt;.&amp;nbsp; If not, you should look at my previous posts on &lt;span class='notranslate'&gt;D-Bus&lt;/span&gt; to gain an understanding of the basic concepts.&lt;br /&gt;&lt;br /&gt;Probably the most commonly used tool is the command line utility &lt;span class='notranslate'&gt;&lt;i&gt;&lt;a href='http://dbus.freedesktop.org/doc/dbus-monitor.1.html'&gt;dbus-monitor&lt;/a&gt;&lt;/i&gt;&lt;/span&gt; which was written by Philip Blundell as part of the reference &lt;span class='notranslate'&gt;D-Bus&lt;/span&gt; implementation and which is standard on most &lt;span class='notranslate'&gt;D-Bus&lt;/span&gt; enabled platforms.&amp;nbsp; It is a very powerful utility but unfortunately it's man page is terse and fails to explain the most powerful feature of &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor&lt;/i&gt;&lt;/span&gt; i.e. &lt;span class='notranslate'&gt;&lt;i&gt;watch expressions&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Suppose, for example, I want to monitor the creation, saving and deletion of &lt;span class='notranslate'&gt;&lt;a href='http://projects.gnome.org/tomboy/'&gt;Tomboy&lt;/a&gt;&lt;/span&gt; &lt;span class='notranslate'&gt;&lt;i&gt;notes&lt;/i&gt;&lt;/span&gt; using &lt;span class='notranslate'&gt;D-Bus &lt;i&gt;signals&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; To get the list of the supported &lt;span class='notranslate'&gt;&lt;i&gt;signals&lt;/i&gt;&lt;/span&gt; I could introspect &lt;span class='notranslate'&gt;Tomboy&lt;/span&gt; using &lt;span class='notranslate'&gt;&lt;i&gt;qdbus&lt;/i&gt;&lt;/span&gt; i.e.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl | grep signal&lt;br /&gt;signal void org.gnome.Tomboy.RemoteControl.NoteAdded(QString uri)&lt;br /&gt;signal void org.gnome.Tomboy.RemoteControl.NoteDeleted(QString uri, QString title)&lt;br /&gt;signal void org.gnome.Tomboy.RemoteControl.NoteSaved(QString uri)&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;or I could use &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor&lt;/i&gt;&lt;/span&gt; to look at the signals generated when &lt;span class='notranslate'&gt;Tomboy&lt;/span&gt; creates, saves and deletes a note.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ dbus-monitor type=signal interface="org.gnome.Tomboy.RemoteControl"&lt;br /&gt;signal sender=org.freedesktop.DBus -&gt; dest=:1.102 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired&lt;br /&gt;   string ":1.102"&lt;br /&gt;signal sender=:1.63 -&gt; dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteAdded&lt;br /&gt;   string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"&lt;br /&gt;signal sender=:1.63 -&gt; dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteSaved&lt;br /&gt;   string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"&lt;br /&gt;signal sender=:1.63 -&gt; dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteDeleted&lt;br /&gt;   string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"&lt;br /&gt;   string "New Note 1"&lt;br /&gt;$&lt;/pre&gt;&lt;/div&gt;As you can see &lt;span class='notranslate'&gt;Tomboy&lt;/span&gt; issues three signals - &lt;span class='notranslate'&gt;&lt;i&gt;NoteAdded&lt;/i&gt;&lt;/span&gt; when a &lt;span class='notranslate'&gt;&lt;i&gt;note&lt;/i&gt;&lt;/span&gt; is added, &lt;span class='notranslate'&gt;&lt;i&gt;NoteSaved&lt;/i&gt;&lt;/span&gt; when a &lt;span class='notranslate'&gt;&lt;i&gt;note&lt;/i&gt;&lt;/span&gt; is saved, and &lt;span class='notranslate'&gt;&lt;i&gt;NoteDeleted&lt;/i&gt;&lt;/span&gt; when a &lt;span class='notranslate'&gt;&lt;i&gt;note&lt;/i&gt;&lt;/span&gt; is deleted.&amp;nbsp; Interestingly, for some reason &lt;span class='notranslate'&gt;&lt;i&gt;NoteDeleted&lt;/i&gt;&lt;/span&gt; provides both the &lt;span class='notranslate'&gt;&lt;i&gt;uri&lt;/i&gt;&lt;/span&gt; and the title of the &lt;span class='notranslate'&gt;&lt;i&gt;note&lt;/i&gt;&lt;/span&gt; whereas the other two &lt;span class='notranslate'&gt;&lt;i&gt;signals&lt;/i&gt;&lt;/span&gt; only provide the &lt;span class='notranslate'&gt;&lt;i&gt;uri&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Suppose I just want to to monitor when a &lt;span class='notranslate'&gt;Tomboy &lt;i&gt;note&lt;/i&gt;&lt;/span&gt; is saved by a user.&amp;nbsp;  I can use a &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor watch expression&lt;/i&gt;&lt;/span&gt; for this purpose as shown in the following example.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;dbus-monitor "type='signal',sender='org.gnome.Tomboy',interface='org.gnome.Tomboy.RemoteControl',path='/org/gnome/Tomboy/RemoteControl',member='NoteSaved'"&lt;/pre&gt;&lt;/div&gt;A &lt;span class='notranslate'&gt;&lt;i&gt;watch expression&lt;/i&gt;&lt;/span&gt; is essentially a message filter.&amp;nbsp; Note the syntax!&amp;nbsp; Everything between the two double quotes is part of the &lt;span class='notranslate'&gt;&lt;i&gt;watch expression&lt;/i&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Unfortunately the syntax of a &lt;span class='notranslate'&gt;&lt;i&gt;watch expression&lt;/i&gt;&lt;/span&gt; is not documented in the &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor&lt;/i&gt;&lt;/span&gt; man page.&amp;nbsp; However from looking at the source code for &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor&lt;/i&gt;&lt;/span&gt;, it appears that a &lt;span class='notranslate'&gt;&lt;i&gt;watch expression&lt;/i&gt;&lt;/span&gt; consists of one or more &lt;span class='notranslate'&gt;&lt;i&gt;name-value&lt;/i&gt;&lt;/span&gt; pairs, e.g. &lt;span class='notranslate'&gt;&lt;i&gt;sender='org.gnome.Tomboy'&lt;/i&gt;&lt;/span&gt; separated by commas.&amp;nbsp; The following are valid &lt;span class='notranslate'&gt;&lt;i&gt;names&lt;/i&gt;&lt;/span&gt;: &lt;span class='notranslate'&gt;&lt;i&gt;type&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;sender&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;destination&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;path&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;interface&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;member&lt;/i&gt;&lt;/span&gt; and &lt;span class='notranslate'&gt;&lt;i&gt;error_name&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; The value of &lt;span class='notranslate'&gt;&lt;i&gt;type&lt;/i&gt;&lt;/span&gt; must be one of the following: &lt;span class='notranslate'&gt;&lt;i&gt;signal&lt;/i&gt;&lt;/span&gt;, &lt;span class='notranslate'&gt;&lt;i&gt;method_call&lt;/i&gt;&lt;/span&gt;,  &lt;span class='notranslate'&gt;&lt;i&gt;method_return&lt;/i&gt;&lt;/span&gt; or &lt;span class='notranslate'&gt;&lt;i&gt;error&lt;/i&gt;&lt;/span&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Probably the most powerful feature of &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor&lt;/i&gt;&lt;/span&gt; is the fact that you are not limited to using just one &lt;span class='notranslate'&gt;&lt;i&gt;watch expression&lt;/i&gt;&lt;/span&gt; at a time.&amp;nbsp; The following example simultaneously monitors all 3 &lt;span class='notranslate'&gt;Tomboy &lt;i&gt;signals&lt;/i&gt;&lt;/span&gt; and uses &lt;span class='notranslate'&gt;&lt;i&gt;awk&lt;/i&gt;&lt;/span&gt; to parse the output from &lt;span class='notranslate'&gt;&lt;i&gt;dbus-monitor&lt;/i&gt;&lt;/span&gt; and display a meaningful message.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;OJECT="'org.gnome.Tomboy'"&lt;br /&gt;IFACE="'org.gnome.Tomboy.RemoteControl'"&lt;br /&gt;DPATH="'/org/gnome/Tomboy/RemoteControl'"&lt;br /&gt;&lt;br /&gt;WATCH1="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteAdded'"&lt;br /&gt;WATCH2="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteSaved'"&lt;br /&gt;WATCH3="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteDeleted'"&lt;br /&gt;&lt;br /&gt;dbus-monitor "${WATCH1}" "${WATCH2}" "${WATCH3}" | \&lt;br /&gt;awk '&lt;br /&gt;/member=NoteAdded/ { getline; print "Created note " substr($2,7) }&lt;br /&gt;/member=NoteSaved/ { getline; print "Added note " substr($2,7) }&lt;br /&gt;/member=NoteDeleted/ { getline; print "Deleted note " substr($2,7) }&lt;br /&gt;'&lt;/pre&gt;&lt;/div&gt;Here is the output generated when I clicked on the &lt;span class='notranslate'&gt;Tomboy&lt;/span&gt; icon to create a new &lt;span class='notranslate'&gt;&lt;i&gt;note&lt;/i&gt;&lt;/span&gt;, waited for the automatic save and then selected the delete option to delete the &lt;span class='notranslate'&gt;&lt;i&gt;note&lt;/i&gt;&lt;/span&gt;.&lt;div class='notranslate'&gt;&lt;pre class='displaybox'&gt;$ ./test&lt;br /&gt;Created note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"&lt;br /&gt;Added note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"&lt;br /&gt;Deleted note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"&lt;/pre&gt;&lt;/div&gt;Well that is all for this post.&amp;nbsp; Enjoy!&lt;br /&gt;&lt;br /&gt;P.S. I tested these examples using Fedora 10. I have no idea whether they will work on previous versions of Fedora or other Linux distributions.&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3795037690945695493-8522778169521719531?l=fpmurphy.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fpmurphy.blogspot.com/feeds/8522778169521719531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fpmurphy.blogspot.com/2009/02/dbus-monitor.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8522778169521719531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3795037690945695493/posts/default/8522778169521719531'/><link rel='alternate' type='text/html' href='http://fpmurphy.blogspot.com/2009/02/dbus-monitor.html' title='Monitoring D-Bus'/><author><name>Finnbarr P. Murphy</name><uri>http://www.blogger.com/profile/02589305657218951462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://1.bp.blogspot.com/_IrJjVkDo0pg/ST8ekxXkFjI/AAAAAAAAAB8/tc_Q5zd9Qx0/S220/1.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3795037690945695493.post-1957742169746061540</id><published>2009-02-07T23:57:00.035-05:00</published><updated>2009-02-15T10:31:09.555-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tomboy'/><category scheme='http://www.blogger.com/atom/ns#' term='D-Bus'/><category scheme='http://www.blogger.com/atom/ns#' term='Shell'/><title type='text'>Scripting Tomboy</title><content type='html'>&lt;span class='notranslate'&gt;&lt;a href='http://projects.gnome.org/tomboy/'&gt;Tomboy&lt;/a&gt;&lt;/span&gt; is an open source &lt;span class='notranslate'&gt;GNOME&lt;/span&gt; desktop note-taki
