Part of the Puzzle: Oracle XMLDB NFS Functionality

This story is long overdue and no its NOT about the Oracle Database 11g Database File System (DBFS). Its about an “undocumented” NFS functionality that, maybe someday, will be serviced by the XMLDB XDB Protocol Adapter. This post is “long overdue” because the actual attempts to try to figure it out were done during the bank holidays between X-mas and new year 2009.

So what is it all about. I once discovered in the Oracle 11gR1 documentation a small entry in the xmlconfig.xsd XML Schema regarding NFS elements that look like that they are or will be used for enabling NFS functionality based on the Oracle XMLDB Protocol Server architecture. In those days, when Oracle 11gR1 was just of the shelve, I made a few attempts, based on the xdbconfig.xsd XML Schema to adjust the corresponding xdbconfig.xml file that controls the XDB Protocol Server functionality, to see what would happen. At that time I only was able to get this far (see the picture) and I promised myself that I should look deeper into it trying to figure out if I could get it working and/or what the concepts were that made it tick in the XMLDB architecture but somewhere down the line I just didn’t come to it and it got “forgotten” by me due to my daily DBA workload.

NFS Protocol Server functionality enabled manually

Click picture to enlarge

The XDB Protocol Server

XML was/is a lot about interfacing. Oracle has from the start with the XMLDB functionality, officially supported since database version 9.2.0.3.0, implemented an enormous amount of W3C and other XML standards. One of this was the need to have a repository. The XDB Protocol Server provides easy access to this repository and on the side opens up database content and functionality you maybe not even aware off. The XDB Protocol Server adapter is build on a very old (Oracle 7) SQL*Net architecture once called “The Multithreaded Server” architecture (MTS) or as it is known nowadays The Shared Server architecture. This architecture was introduced in those Oracle 7 days to minimize the memory resources of dedicated SQL*Net connections of the corresponding server processes in a decade that memory was still incredible expensive.

Click picture to enlarge

You can control the functionality of this XDB Protocol Server adapter architecture on three levels:

  • Via the Listener: the listener.ora and other related configuration files
  • Via the Database: by setting database parameters via the pfile or spfile database configuration file(s)
  • Via the Protocol Server adapter: xdbconfig.xml configuration file

In its behavior and possibilities the xdbconfig.xml file has a lot in its look and feel like the Apache httpd.conf file or a server.xml file of an Application Server. The configuration defines for example MIME types, memory and locking behavior, configuration of “servlets” (naming probably derived from the WebDAV definitions) like HTTP, FTP, Native Database Web Services (NDWS), PL/SQL Gateways like local APEX support, security, etc., etc.

Click picture to enlarge

The xdbconfig.xml file is restricted by one of the by Oracle defined XML Schemata called “xdbconfig.xsd” and you will need the XDBADMIN database role to alter its content. These schemata are located in the “sys” directory of the XDB Repository. Be aware that you should treat this “sys” directory (or so called “resource” in WebDAV terms) as if it were the SYS user schema in the database. Oracle will uphold its right to alter the structures in this directory as it pleases, also regarding the (ACL) security, versioning etc. So never use this “sys” directory/resource or sub-directories as a placeholder for you application files or resources.

Click picture to enlarge

So within the limits of the xdbconfig.xsd, you could add you own specific protocol server needs in terms of extra PL/SQL gateway definitions or adding MIME types, so you would be able to trigger a by you defined method to act on a certain file extension or file extension content. The xdbconfig.xml file which is actually a record in a table called XDB$CONFIG is protected by Access Control Lists (ACL), underneath enforced by Oracle’s VPD methods. Due to the fact that Oracle is using VPD internally to make this work, to enforce ACL security, this part is free of license as is Oracle XMLDB functionality by the way.

Click picture to enlarge

Besides acting as a web server (HTTP/HTTPS), Oracle build in, by default, FTP access (FTP Server functionality), the mentioned Native Database Web Service (the database acts as a web service), and support for its own applications (APEX, a servlet called “ReportFmwkServlet” for DB Console / OEM reporting) and the “DBURI” servlet, which makes it possible to query (via XPath) and report database table content.

These so called Servlets can make use of Java, PL/SQL or C interfacing methods. The C related servlets, like the NDWS, DBURI and “ReportFmwkServlet” hook directly into the Oracle kernel and are, regarding its internal workings, only known to Oracle and not further documented. That is, the only thing that is described, is how they can be enabled and how they should be used.

But there is more.

Another cool feature is that XDB Repository actions/events can be triggering by an Oracle defined action/method (e.g. shredding XML data directly into a corresponding table after being FTP-ed or drag/dropped by WebDAV in the XDB Repository) or, as of Oracle 11gR1, user actions/methods. The latter is called “Repository Events“. Repository Events are events which get triggered via defined methods on the Repository. These XDB Repository Events need defining an “Event Listener“, an “Event Handler” and a “Event Configuration” file, which hooks everything together.

Be aware that a Repository Event is NOT a database trigger. Also a repository operation can be associated with one or more repository events. To name a few: creating, deleting, locking, unlocking, placing under version control, checking in, checking out, unchecking out, opening, and/or updating a resource (aka a file or folder).

If you need more info and/or examples, have a look at the “XFiles” XMLDB Demo Application that demonstrates, among others, lightweight content management functionality, NDWS and more.

Trying to figure out XDB NFS Functionality

Now that you have an overview, where does this XDB NFS kickin in all of this? In the current latest release, Oracle 11gR2, the existence of this XDB NFS functionality can be found via accessing the configuration web pages of the local DB Console. In the DB Console server menu tab, you can find the XDB Configuration URL and after clicking it you will see the following page in Oracle 11gR2.

Click picture to enlarge

Clicking on the “ENABLE” button will bring you in the “exports” and NFS port configuration file.

Click picture to enlarge

After configuring and exporting, for example, the /public and /home of the WebDAV / XDB Repository directories and its resources (aka files) and clicking on the “OK” button, the xdbconfig.xml configuration file will have been updated and the listener will show a status that has an extra entry for the servicing the NFS protocol. IN 2007 I did configure the NFS entries by hand based on the xmlconfig.xsd XML Schema. The DB Console pages will do this for you.

Trying to figure out how all elements hooked in each other I started searching and tracing from the inside out (database, protocol server, listener, OS) or at least described here in “reverse” order.

The Database Part

I am guessing that the NFS XDB functionality probably hooks into a C kernel based “servlet” somehow. At least part of it already can be controlled my the xdbconfig.xml file and the user XDB has a table called XDB$ROOT_INFO that supports NFS entries.

SQL> sho user

USER is "XDB"

SQL> desc XDB$ROOT_INFO

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 RESOURCE_ROOT                                      ROWID
 RCLIST                                             RAW(2000)
 FTP_PORT                                           NUMBER(5)
 FTP_PROTOCOL                                       VARCHAR2(4000)
 HTTP_PORT                                          NUMBER(5)
 HTTP_PROTOCOL                                      VARCHAR2(4000)
 HTTP_HOST                                          VARCHAR2(4000)
 HTTP2_PORT                                         NUMBER(5)
 HTTP2_PROTOCOL                                     VARCHAR2(4000)
 HTTP2_HOST                                         VARCHAR2(4000)
 NFS_PORT                                           NUMBER(5)
 NFS_PROTOCOL                                       VARCHAR2(4000)

Other semi build in table structures that can be found in the XDB user schema or the 11gR2 database that are or that probably are XMLDB NFS related:

SQL> desc XDB$CONFIG

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
TABLE of SYS.XMLTYPE(XMLSchema "http://xmlns.oracle.com/xdb/xdbconfig.xsd" Element "xdbconfig") STORAGE BINARY

SQL> desc SERVLET

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
TABLE of SYS.XMLTYPE(XMLSchema "http://xmlns.oracle.com/xdb/XDBStandard.xsd" Element "servlet") STORAGE Object-relational TYPE "SERVLET_T"

SQL> desc "SERVLET_T"

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SYS_XDBPD$                                         XDB$RAW_LIST_T
 icon                                               VARCHAR2(4000 CHAR)
 servlet-name                                       VARCHAR2(4000 CHAR)
 servlet-language                                   XDB$ENUM_T
 display-name                                       VARCHAR2(4000 CHAR)
 description                                        VARCHAR2(4000 CHAR)
 servlet-class                                      VARCHAR2(4000 CHAR)
 jsp-file                                           VARCHAR2(4000 CHAR)
 servlet-schema                                     VARCHAR2(4000 CHAR)
 load-on-startup                                    VARCHAR2(4000 CHAR)
 security-role-ref                                  security-role-ref6_COLL

SQL> desc "security-role-ref6_COLL"

 "security-role-ref6_COLL" VARRAY(65535) OF security-role-ref5_T

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SYS_XDBPD$                                         XDB$RAW_LIST_T
 description                                        VARCHAR2(4000 CHAR)
 role-name                                          VARCHAR2(4000 CHAR)
 role-link                                          VARCHAR2(4000 CHAR)

SQL> desc XDB$MOUNTS

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DOBJ#                                              NUMBER
 DPATH                                              VARCHAR2(4000)
 SOBJ#                                              NUMBER
 SPATH                                              VARCHAR2(4000)
 FLAGS                                              NUMBER

SQL> desc DBMS_XDBNFS

SQL> select * from table( myunwrapper( 'DBMS_XDBNFS','XDB', null));

COLUMN_VALUE
-----------------------------------------------------------------------
PROCEDURE DUMP_NFSSTATS

FUNCTION NFSFH2RESID RETURNS RAW
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 FH                             RAW                     IN

PROCEDURE RESET_NFSSTATS
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SKIP                           BINARY_INTEGER          IN
 TRACE                          BINARY_INTEGER          IN

PROCEDURE SYNCRESOURCE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 RESID                          RAW                     IN

PACKAGE BODY DBMS_XDBNFS AS

FUNCTION NFSFH2RESID(FH IN RAW) RETURN RAW IS
BEGIN
  RETURN SUBSTR(FH, 1, 32);
END;

PROCEDURE SYNCRESOURCE(RESID IN RAW) IS
  EXTERNAL
  NAME "DBMSXDB_SYNC_RESOURCE"
  LANGUAGE C
  LIBRARY DBMS_XDB_LIB
  WITH CONTEXT
  PARAMETERS (CONTEXT,
              RESID   RAW,
              RESID   INDICATOR SB4,
              RESID   LENGTH SB4);

PROCEDURE DUMP_NFSSTATS IS
  EXTERNAL
  NAME "DBMSXDB_DUMPNFSSTATS"
  LANGUAGE C
  LIBRARY DBMS_XDB_LIB;

PROCEDURE RESET_NFSSTATS(SKIP IN PLS_INTEGER, TRACE IN PLS_INTEGER) IS
  EXTERNAL
  NAME "DBMSXDB_RESETNFSSTATS"
  LANGUAGE C
  LIBRARY DBMS_XDB_LIB
  WITH CONTEXT
  PARAMETERS (CONTEXT,
              SKIP           UB4,
              TRACE          UB4);

END DBMS_XDBNFS;

SQL> set head off
SQL> select * from DBA_SCHEDULER_JOBS where JOB_NAME in ('XMLDB_NFS_CLEANUP_JOB');

SYS                            XMLDB_NFS_CLEANUP_JOB
                               REGULAR     SYS
STORED_PROCEDURE
xdb.dbms_xdbutil_int.cleanup_expired_nfsclients
                  0
CALENDAR
Freq=minutely;interval=5
XMLDB_NFS_JOBCLASS             FALSE TRUE  FALSE DISABLED                   3
         0                        0                        0
OFF         FALSE TRUE

Anyway, testing set NFS functionality revealed that it has to be set after database start-up and for now doesn’t automatically load-on-startup, even after entering/updating for example table XDB$ROOT_CONFIG with the proper values.

The Protocol Server Part

Tracing the functionality as described in “ORA-31098: Internal event to turn on XDB tracing”, even combined with tracing on the appropriate shared server process id via the Oracle support facility called oradebug

Methods used where setting the event 31089 XDB protocol trace event on database level, like in the following example or higher and combining it with the 10046 event set via oradebug for the proper shared server process.

-- Used level 2 and higher to trace
SQL> alter system set event= '31098 trace name context forever, level 2' scope=spfile;

SQL> oradebug setorapid 18
Oracle pid: 18, Unix process pid: 28368, image: oracle@srv01-18-102.amis.local (S000)

SQL> oradebug event 10046 trace name context forever, level 12
Statement processed.

-- To disable the event
-- SQL> ORADEBUG EVENT 10046 TRACE NAME CONTEXT OFF
-- Statement processed.

As you can see/read, I had way to much time, to search the database, but then again working in between bank holidays can be a very quiet and productive time. What helps as well b.t.w. is using a Linux or Unix environment and search, for example, with some “grep” statements through the $ORACLE_HOME/rdbms/admin scripts. Searching through those scripts I found also hints that Oracle started thinking or building this functionality in approximately during/after the year 2005, based on the comments in the header of those scripts.

The Listener / OS part

Initially when I started it took me a while that by default Oracle Enterprise Linux has NFS services running in its “out of the box” state (not OK I think), So after stopping or even killing every NFS related daemon or service I started tracing on the Oracle listener part. Stopping every NFS part on the OS side is important due to the fact that otherwise the enabled port on the listener side (in my case 2049) will be blocked due to the fact that the defined port has already been taken by an OS daemon/service or maybe could trigger other “smart” processes like portmapper and others. In all intervening with my mount / trace attempts.

So the setting was as follows:

[root@srv01-18-103 oranfs]# su - oracle -c 'lsnrctl status'

LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 28-DEC-2009 14:31:38
Copyright (c) 1991, 2009, Oracle.  All rights reserved.
Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))

STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.2.0.1.0 - Production
Start Date                15-DEC-2009 18:24:37
Uptime                    12 days 20 hr. 7 min. 1 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Log File         /u01/app/oracle/diag/tnslsnr/srv01-18-103/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=srv01-18-103.amis.local)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=srv01-18-103.amis.local)(PORT=8080))(Presentation=HTTP)(Session=RAW))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=srv01-18-103.amis.local)(PORT=2100))(Presentation=FTP)(Session=RAW))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=srv01-18-103.amis.local)(PORT=2049))(Presentation=NFS)(Session=RAW))
Services Summary...
Service "ORCL" has 1 instance(s).
  Instance "ORCL", status READY, has 1 handler(s) for this service...
Service "ORCLXDB" has 1 instance(s).
  Instance "ORCL", status READY, has 1 handler(s) for this service...

The command completed successfully

I created a directory on the Linux side /oranfs/public and opened it up for the world regarding its security settings (btw secure linux is not enabled on my test OEL linux system nor any firewall). I attempted connections / mount options via the NFS3 and NFS4 protocols but both weren’t successful (at least that was what I thought) via variations on the following:

[root@srv01-18-103 oranfs]# mount -v -t nfs srv01-18-103:2049/public /oranfs/public -o ro,sync,auto,hard,intr

mount: Unable to connect to 10.252.252.103:111, errno 111 (Connection refused)
mount: trying 10.252.252.103 prog 100003 vers 3 prot tcp port 49096
mount: Unable to connect to 10.252.252.103:49096, errno 111 (Connection refused)
mount: mount to NFS server 'srv01-18-103' failed: System Error: Connection refused.

[root@srv01-18-103 oranfs]# mount -v -t nfs srv01-18-103:/public /oranfs/public -o ro,sync,auto,hard,intr

mount: Unable to connect to 10.252.252.103:111, errno 111 (Connection refused)
mount: trying 10.252.252.103 prog 100003 vers 3 prot tcp port 49096
mount: Unable to connect to 10.252.252.103:49096, errno 111 (Connection refused)
mount: mount to NFS server 'srv01-18-103' failed: System Error: Connection refused.

I had enabled the listener to trace on support level via the following so I could follow if at least the listener would try to pick up the mount request and do a hand off to a part in the database.

LSNRCTL> set trc_level 16

Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER parameter "trc_level" set to support

The command completed successfully

I will spare you the whole listener and trace file (you could try it yourself anyway if your interested), but using the NFS4 protocol mount options were picked up by the listener.

-- listener.log
Thu Dec 31 12:34:46 2009
31-DEC-2009 12:34:46 * NFS * (ADDRESS=(PROTOCOL=tcp)(HOST=10.252.252.103)(PORT=65128)) * handoff * NFS * 0

and in the trace file…

...
2009-12-31 12:34:46.775605 : nsglnphc:Connected with client. Protocol: tcp  Presentation: NFS.
...
and a bit later
...
2009-12-31 12:34:46.787677 : nsbequeath:NSE=12586
2009-12-31 12:34:46.787784 : nsbequeath:error reading REDIR/NSE msg
...

Summery

What did I learn? In principal not that much, just that some of the structures (or residue depending on the view) regarding XDB NFS Protocol Server adapter support is build in. On the other hand, besides the tedious monk work regarding trace 31098 levels, the whole exercise crawling through all those database setup and installation scripts, the tracing as is, and deep dive into database parts gave me a better understanding and insight of the internal workings of it all.

I would really like to see this functionality in a next release, not only because I think that the Securefile Development team functionality of the Database File System (DBFS) is a bit of a fuzz on pointers like having to use FUSE and a DBFS client to make it all happen. Despite they did great work to make it happen in the first place, but being me a XMLDB nerd, why not use a much more simpler set-up without all those prerequisites. The XDB Repository and the XDB Protocol Server architecture have so much to offer in terms of extra’s along the side like “Repository Events“, ACL Security build-in, Versioning, etc, to just name a few.

And yes, XMLDB has also a lot of hook-ins regarding securefile support or for instance DICOM support as a old “XFiles” demo application will prove automatically recognizing EXIF information in JPG/PNG and other pictures. Oracle please implement it after all, if not only due to enabling an extra possibility to exchange XML based data.

Just an idea.

M.

Want to see it all in action?

I will be giving some demonstrations on the mentioned subject in this post during a presentation of mine called: “Boost your environment with Oracle XMLDB”. You can attend this presentation during the “MOTS” and “MOW” events this year.

  • Miracle OpenWorld, 14-16 April, Denmark
  • The Michigan OakTable Symposium, 16-17 September, Michigan, USA
Marco Gralike Written by: