Managing Containers

In BDB XML you store your XML Documents in containers. A container is a file on disk that contains all the data associated with your documents, including metadata and indices.

To create and open a container, you use XmlManager::createContainer(). Once a container has been created, you can not use createContainer() on it again. Instead, simply open it using: XmlManager::openContainer().

Note that you can test for the existence of a container using the XmlManager::existsContainer() method. This method should be used on closed containers. It returns 0 if the named file is not a BDB XML container. Otherwise, it returns the underlying database format number.

Alternatively, you can cause a container to be created and opened by calling openContainer() and pass it the necessary flags to allow the container to be created (see the following section for information on container open flags).

You can open a container multiple times. Each time you open a container, you receive a reference-counted handle for that container.

You close a container by allowing the container object to go out of scope. Note that the container is not actually closed until the last handle for the container is off the stack.

For example:

#include "DbXml.hpp"
...

using namespace DbXml;
int main(void)
{
    XmlManager myManager;   // The manager is closed when
                            // it goes out of scope.

    // Open the container. If it does not currently exist, 
    // then create it. This container is closed when the last
    // handle to it goes out of scope.
    XmlContainer myContainer = 
        myManager.createContainer("/export/xml/myContainer.bdbxml");

    // Obtain a second handle to the container.
    XmlContainer myContainer2 =
        myManager.openContainer("/export/xml/myContainer.bdbxml");

    return(0);
} 

Container Flags

When you create or open a container, there are a large number of flags that you can specify which control various aspects of the container's behavior. The following are the flags commonly used by BDB XML applications. For a complete listing of the flags available for use, see the BDB XML API Reference.

As is the case with environment flags, to set multiple flags you must bitwise or them together:

       DB_CREATE | DB_EXCL
  • DB_CREATE

    Causes the container and all underlying databases to be created. It is not necessary to specify this flag on the call to XmlManager::createContainer(). In addition, you need specify it for XmlManager::openContainer(). only if the container has not already been created.

  • DB_EXCL

    Causes the container creation to fail if the container already exists. It is not necessary to specify this flag on the call to XmlManager::createContainer(). Note that this flag should only be used if DB_CREATE is also used.

  • DB_RDONLY

    The container is opened for read-access only.

  • DBXML_ALLOW_VALIDATION

    Causes documents to be validated when they are loaded into the container. The default behavior is to not validate documents.

  • DBXML_INDEX_NODES

    Causes indices for the container to return nodes rather than documents. The default is to index at the document level. This flag has no meaning if the container type is WholedocContainer (see below).

    This flag is only meaningful at container creation time; you cannot change the indexing level once the container has been created.

    For more information on index nodes, see Specifying Index Nodes.

  • DBXML_TRANSACTIONAL

    The container supports transactions. For more information, see Berkeley DB XML Getting Started with Transaction Processing guide.

Container Types

At creation time, every container must have a type defined for it. This container type identifies how XML documents are stored in the container. As such, the container type can only be determined at container creation time; you cannot change it on subsequent container opens.

Containers can have one of the following types specified for them:

  • Wholedoc Containers

    The container contains entire documents; the documents are stored "as is" without any manipulation of line breaks or whitespace. To cause the container to hold whole documents, set XmlContainer::WholedocContainer on the call to XmlManager::createContainer().

  • Node containers

    XmlDocuments are stored as individual nodes in the container. That is, each record in the underlying database contains a single leaf node, its attributes and attribute values if any, and its text nodes, if any. BDB XML also keeps the information it needs to reassemble the document from the individual nodes stored in the underlying databases.

    This is the default, and preferred, container type.

    To cause the documents to be stored as individual nodes, set XmlContainer::NodeContainer on the call to XmlManager::createContainer().

  • Default container type.

    The default container type is used. You can set the default container type using XmlManager::setDefaultContainerType(). If you never set a default container type, then the container will use node-level storage.

Note that NodeContainer is generally faster to query than is WholedocContainer. On the other hand, WholedocContainer provides faster document loading times into the container than does NodeContainer because BDB XML does not have to deconstruct the document into its individual leaf nodes. For the same reason, WholedocContainer is faster at retrieving whole documents for the same reason — the document does not have to be reassembled.

Because of this, you should use NodeContainer unless one of the following conditions are true:

  • Load performance is more important to you than is query performance.

  • You want to frequently retrieve the entire XML document (as opposed to just a portion of the document).

  • Your documents are so small in size that the query advantage offered by NodeContainer is negligible or vanishes entirely. The size at which this threshold is reached is of course dependent on the physical resources available to your application (memory, CPU, disk speeds, and so forth).

Note that you should avoid using WholedocContainer if your documents tend to be greater than a megabyte in size. WholedocContainer is tuned for small documents and you will pay increasingly heavy performance penalties as your documents grow larger.

For example:

#include "DbXml.hpp"
...

using namespace DbXml;
int main(void)
{
    XmlManager myManager;   // The manager is closed when
                            // it goes out of scope.

    myManager.setDefaultContainerType(XmlContainer::WholedocContainer);

    // Create and open the container.
    XmlContainer myContainer = 
        myManager.createContainer("/export/xml/myContainer.bdbxml");
    return(0);
} 

Deleting and Renaming Containers

You can delete a container using XmlManager::removeContainer(). It is an error to attempt to remove an open container.

You can rename a container using XmlManager::renameContainer(). It is an error to attempt to rename an open container.

For example:

#include "DbXml.hpp"
...

using namespace DbXml;
int main(void)
{
    XmlManager myManager;   // The manager is closed when
                            // it goes out of scope.

    // Assumes the container currently exists.
    myManager.renameContainer("/export/xml/myContainer.bdbxml",
                              "/export2/xml/myContainer.bdbxml");


    myManager.removeContainer("/export2/xml/myContainer.bdbxml");

    return(0);
}