Lesson 2: Database Operation and Maintenance

Both Active Directory and Exchange 2000 Server utilize the ESE database engine (ESE.DLL), which in turn manages a variety of database files to ensure data integrity and consistency even in the event of a system crash. In Active Directory, an ESE database holds the configuration information of your organization. In Exchange 2000 Server, ESE databases form information stores and storage groups. Other services, such as Site Replication Service (SRS), Key Management Service (KMS), and the MS Mail directory synchronization also use ESE. It is important to have a thorough understanding of this technology and its maintenance.

This lesson emphasizes the maintenance of Exchange 2000 Server databases. It starts with an explanation of the database characteristics and continues with a discussion of available backup strategies. Low-level database maintenance tools that are at your disposal are introduced.


At the end of this lesson, you will be able to:

  • Identify Exchange 2000 databases and corresponding files according to their tasks.
  • Use low-level maintenance utilities to compact information store databases.

Estimated time to complete this lesson: 75 minutes


Considerations About Information Stores

Exchange 2000 Server is designed to accommodate a reasonable number of mailboxes and public folders. Its databases can grow beyond all limits up to the capacity of the server's storage system. Several system improvements allow you to consolidate your resources on fewer but larger servers. Benchmark tests prove that Exchange 2000 Server is very scalable. However, extreme limits, such as hundreds of thousands of mailboxes and millions of daily messages per server, do not have a perfect correlation to real-world environments. Server benchmarks are prepared to compare upper limits of competitive platforms with each other, but they do not reflect business requirements or outline deployable scenarios.

Information Store Database Sizes

One important consideration in determining the maximum number of users per server is the resulting size of the information store database files. The more users hold data in their mailboxes and the larger the databases, the longer it will take to back up and restore the system. High-performance backup solutions may be able to save between 25 GB and 50 GB per hour. Again, however, this is a benchmark. It is not realistic to assume a restore rate of 50 GB per hour on a RAID 5 subsystem because checksum recalculation and other factors will slow down the restore. You may be able to achieve a restore rate of 20 GB per hour. Therefore, if you had to recover a server with 10,000 mailboxes, each holding an average of just 20 MB of data, you would have to restore about 200 GB of data. At 20 GB restored per hour, your server would be down for at least 10 hours, not including time to rebuild server hardware and recover the operating system. If 10,000 users cannot work for 10 hours, altogether 100,000 work hours are lost—that's 12,500 workdays or approximately 62 work years (using 200 workdays/year).

Fortunately, it is possible to bring back a crashed Exchange 2000 server very quickly without restoring its databases right away. The server is empty temporarily, but your users could continue their work while you fill the mailboxes with restored data in the background. The high-speed system recovery is explained in Lesson 3.

Multiple Information Store Databases and Storage Groups

If you plan to implement heavyweight servers, you should split mailbox resources across multiple small databases. Exchange 2000 Server supports maintenance operations for individual databases without affecting other stores. Small databases are more quickly restored. It is possible to create up to five stores in a single storage group and a total of four storage groups, which gives you the ability to create up to 20 information store databases.

You may find it useful to create a separate mailbox store for very important persons and configure a different backup schedule for it. As discussed in Chapter 14, "Managing Server Configuration," all databases in a storage group share the same set of transaction log files and should therefore be included in the same backup. For that reason, create multiple storage groups and distribute mailbox stores across them accordingly.

NOTE


It is not advisable to create a separate database for each individual manager's mailbox. Delegate access to a mailbox (see Exercise 5 of Chapter 8, "Microsoft Outlook 2000 Deployment") does not work between different mailbox stores on the same physical Exchange 2000 server due to a limitation in the client's Exchange transport service. Furthermore, the single-instance storage feature is not available across multiple stores.

Defining the Databases

Exchange 2000 Server databases can be divided into two groups: core databases and additional databases. Core databases maintain user data, and additional databases are required in particular situations. All existing databases should be included in maintenance and backup operations.

Core Databases

The core databases belong to the Information Store service. The databases of the default mailbox store are called PRIV1.EDB and PRIV1.STM, and PUB1.EDB and PUB1.STM for the default public store. These files can be found in the \Program Files\Exchsrvr\Mdbdata directory. As explained in Chapter 14, "Managing Server Configuration," you can create additional databases and place them in arbitrary directories on the server's local disks.

Each store consists of an .edb and an .stm database. The Exchange database (.edb) contains data in standard rich text Messaging Application Programming Interface (MAPI)-based format. The Exchange streaming database (.stm) supports streaming Multipurpose Internet Mail Extensions (MIME) content directly into the store without conversion. For instance, if the Information Store service receives a message from Internet Information Services (IIS), the header information, such as From, To, CC, BCC, Delivery Time, and so on, is converted to MAPI and stored in the .edb file. The message contents, on the other hand, are stored in the .stm file. To give another example, if you save a Microsoft Word document directly into a public folder library using the Microsoft Web Storage System, the document is streamed into the .stm file and document properties are promoted to the .edb file. This is illustrated in Exercise 1 of Chapter 21, "Microsoft Outlook Forms Environment." When you access the same file from within Outlook 2000, the entire file is converted into a MAPI object before it is delivered to the client. Deferred content conversion saves time and system resources because items are only processed when necessary.

NOTE


You can rename .edb and .stm databases and move them to different directories. Right-click the corresponding information store, select Properties, click on the Database tab, and then click the corresponding Browse buttons to specify the new locations. However, because the .edb and .stm files build a complete store, it is advisable to keep them together and assign them a common name with different extensions (that is, .edb and .stm). Moving databases temporarily dismounts the affected store. You should perform a full backup immediately after moving databases.

Optional Databases

As explained in Chapter 6, "Coexistence with Previous Microsoft Exchange Server Versions," Active Directory Connector (ADC) and SRS coordinate the replication between Active Directory and the legacy Exchange directory if you install Exchange 2000 Server in an existing Exchange Server organization. The SRS emulates an Exchange Server 5.5 directory service and maintains its own database called SRS.EDB, which can be found in the \Program Files\Exchsrvr\Srsdata directory. SRS.EDB contains configuration information replicated with the Exchange directory service. It is possible to back up the SRS database online using the Exchange 2000 Server-enabled version of the Windows 2000 Backup utility, which is covered in Lesson 3.

The KMS database called KMSMDB.EDB resides in the \Program Files\Exchsrvr\Kmsdata directory, provided that you have installed KMS on the local computer. This database preserves the history of the encryption keys for all users who have been enabled with advanced security. You can back up the KMS database online using an Exchange 2000 Server-enabled backup utility. Do not forget to secure the KMS database and your KMS administrator password. Likewise, make sure a correct backup of Windows 2000 Certificate Services is performed. At a minimum, back up your certification authority's (CA) certificate in a .p12 file and save the password. KMS was covered in Chapter 19, "Implementing Advanced Security."

The Dirsync database, called XDIR.EDB, is located in the \Program Files\Exchsrvr\Dxadata directory. It keeps track of MS Mail directory synchronization (Dirsync) transactions. The Dirsync Agent uses this database when directory synchronization with MS Mail has been configured. Losing this database is not a disaster, but you should save the Dirsync database offline using a file-based backup to avoid resetting the Dirsync. You can read more about directory synchronization with MS Mail in Chapter 26, "Connecting to Microsoft Mail and Schedule+."

The Microsoft Search service maintains the database with perhaps the longest name. If you have enabled full-text indexing, a database file called EXCHANGESERVER_<Server Name>.EDB (such as EXCHANGESERVER_BLUESKY-SRV1.EDB) will exist in the \Program Files\Exchsrvr\EXCHANGESERVER_<Server Name> directory. The full-text search database must be backed up offline using a file-based backup. You can read more about full-text indexing in Chapter 14, "Managing Server Configuration."

Main Database Components

If you check out any of the database locations, such as the \Program Files\Exchsrvr\Mdbdata directory, you will find that the .edb and .stm databases are not the only existing items (see Figure 20.6). A number of .log files exist, along with a .chk file and TMP.EDB. TMP.EDB is not important because it contains temporary information that is deleted when all stores in the storage group are dismounted or the Information Store service is stopped. TMP.EDB is not included in backups. However, the .log and .chk files are essential for the fault-tolerant, transaction-based ESE.

Transaction Logs

Transaction log files give ESE the ability to manage data storage efficiently with high speed. ESE stores new transactions, such as the delivery of a message, in a memory cache and in the transaction log concurrently. The data is written sequentially, with new data appended to existing data without the need for complex database operations. At a later time, the transactions are transferred en masse from the memory cache to the actual databases to bring them up to date.

click to view at full size

Figure 20.6 Important database files

You can determine the path to a storage group's transaction log file and its name in Exchange System Manager. Right-click the desired storage group, select Properties, and in the General tab, check the Transaction Log Location and the Log File Prefix fields. By default, the First Storage Group maintains its transactions logs in the same directory as the databases and uses the prefix E00, which results in a transaction log file name of E00.LOG. The E00.LOG is used for all mailbox and public stores in this storage group. If you create additional storage groups, the prefix number is incremented to E01, E02, and E03.

Checkpoint Files

The ESE memory cache greatly improves system performance, but this cache may be lost due to a sudden power outage or system failure before the transactions are written to the database. Transaction logs ensure that committed transactions are not lost. When you restart the server, Exchange 2000 Server reads the checkpoint file (for example, E00.CHK), determines the transactions that require processing, and incorporates these into the databases from the log files.

Checkpoint files are updated whenever ESE writes a particular transaction into a database, so the checkpoint file always points to the last transaction that was transferred successfully. This provides a fast recovery mechanism, although checkpoint files are not required to commit transactions to databases. ESE can also process transaction log files directly, determining by itself which transactions have not yet been transferred, but this takes significantly more time. Nevertheless, ESE guarantees that transactions are not written to databases multiple times.

Previous Logs

Transaction log files are always exactly 5.242.880 bytes (5 MB) in size. If a log is completely used, it is renamed to allow the creation of a new, empty file. Renamed transaction logs are called previous log files. The naming format of previous log files is <Log Prefix>XXXXX.LOG (such as E00XXXXX.LOG), where XXXXX represents a five-digit hexadecimal number from 00000 to FFFFF. Previous logs reside in the same directories as the current transaction log file.

Reserved Logs

Reserved logs are an "emergency repository" for transactions. They provide enough disk space to write them from memory to the hard disk even if a server's disk is filled to a point where no new transactions can be added to a log file. Reserved logs are called RES1.LOG and RES2.LOG and can be found in the transaction log directories. They are created automatically when the databases are initialized because—for obvious reasons—they cannot be created later when they are actually needed.

ESE uses RES1.LOG and RES2.LOG only to complete a current transaction process. It then sends an error notification to the store or other service, depending on which database is affected, to shut down the service safely. You will find an entry that indicates the service shutdown along with a description of the reason in the application event log. In this situation, you should create additional free hard disk space (for example, add a new hard disk) before you restart the services. Another possible option is to restart the services immediately and perform a full backup of the databases. This deletes existing transaction logs and frees the server's hard disk resources. The full backup is explained in Lesson 3.

Patch Files

The Exchange 2000 Server version of the NTBACKUP.EXE program allows you to perform backup operations while the server services are running. This means that while you are saving the server databases and transaction log files, users can still send and receive messages. Patch files (such as PRIV1.PAT and PUB1.PAT) catch these current transactions. They are included in the current backup at the end of the operation and incorporated into the databases afterward. Patch files should not exist during regular server operation.

NOTE


Patch files ensure that the current online backup represents the most recent state.

Log File Maintenance and Circular Logging

Exchange 2000 Server holds each transaction in two file-based repositories: the transaction log and the databases. Consequently, it is possible to restore a database from an uninterrupted sequence of transaction log files since the time the database was created (or last backed up). Because transaction log files are important for data recovery, Exchange 2000 Server does not delete them automatically.

Manual Deletion

Manually deleting transaction log files is not advisable because you run the risk of corrupting the databases. You cannot analyze the checkpoint files to figure out which transactions have already been transferred. Manual deletion will lead to inconsistent databases, which will not be recoverable without a recent backup.

Database Backups

Transaction log files are deleted when you complete a full or an incremental backup. As mentioned earlier, if you need to free hard disk space, perform a full online backup. This is the safest way of deleting transaction logs.

NOTE


Because all databases within a storage group share the same set of log files, transaction logs are deleted only after all databases have been backed up. This is one reason you should configure backup operations for entire storage groups.

Circular Logging

Circular logging basically means automatically deleting transaction log files and their entries. Circular logging causes the server to discard transactions as soon as they have been committed to the databases. The checkpoint file indicates which log files and transaction entries can be removed. Any existing previous logs are deleted, while transactions within the current transaction log file are marked as obsolete only. New transactions will eventually overwrite the obsolete entries in the current transaction log before a new log file is created as usual.

Circular logging prevents duplicate consumption of disk space, but it is not compatible with sophisticated fault-tolerant configurations and several online backup types, which rely on the existence of transaction logs. You might therefore want to enable this feature only for less important repositories that hold a large amount of data, such as Network News Transport Protocol (NNTP)-based newsgroups implemented in a public store. Right-click the storage group for which you want to enable circular logging, select Properties, and in the General tab, select the Enable Circular Logging check box.

NOTE


It is not recommended that you enable circular logging for storage groups that hold business-relevant data. With circular logging enabled, you can only recover information included in the last full backup.

Database Partitioning

Each storage group requires a directory for its transaction logs, but this location does not need to be the directory for the databases. If your Exchange 2000 server is equipped with multiple hard disk systems, separating transaction logs from databases can greatly improve your ability to recover the system in the event of a hardware failure.

Transaction Log Location

Disks of transaction log files should not contain any Exchange databases. Furthermore, as ESE maintains separate transaction log files for each storage group, it is advantageous to place the logs of each storage group on separate physical disks, if possible. At first glance, it may seem that this decreases the system reliability because more hard disk systems, which can fail, are added to the server. However, if you kept the transaction log files of all your storage groups on a single dedicated disk system and that system failed, your entire server would be out of order. With transaction logs on separate disks, only a particular storage group will be affected while users with mailboxes in other storage groups can continue to work in Outlook 2000 as if nothing has happened.

It is a Microsoft recommendation to separate transaction log disks per storage group to increase the system resilience. It is a good idea to protect the transaction log disks with RAID, for example, by creating a mirror. If a particular hard disk holding a set of transaction logs breaks, you can split the mirror set and remove the problematic device. Your server will be fully operational again. During a later maintenance cycle, you may add a new disk and reconfigure the mirror set.

Separate transaction log disks may also improve the system performance because ESE threads can then write transactions for separate storage groups to the transaction log files concurrently. Separate disk controllers do not block each other's Input/Output (I/O) operations. However, this configuration does not keep its promises if the majority of activities happen in one particular storage group. A single disk controller would then have to accomplish all the work. Consequently, you achieve better performance by consolidating the disks that would be used for all transaction logs and placing them into a single RAID array (for instance, a mirrored stripe set). Striping the hard disks together improves disk I/O because I/O requests are spread evenly across all disk controllers—even if only a single storage group shows activity.

NOTE


A problematic storage group or database will not prevent the Information Store service from running. Unaffected databases remain mounted and available.

Database Location

It is not required to place the databases of each storage group on separate hardware-level RAID volumes. A stripe set with parity, or any other advanced RAID configuration (such as a mirrored or duplexed stripe set), may provide the required level of protection against hardware failures. If one disk breaks, it can be replaced without data losses. Total damage of the RAID system, however, would affect all storage groups of your server. Very cautious administrators may therefore want to implement separate physical disk sets for the databases of each storage group (see Figure 20.7). If one particular disk set indicates problems, affected databases may be moved, dismounted, or restored without affecting stores in other storage groups.

click to view at full size

Figure 20.7 An ambitious disk subsystem for Exchange 2000 Server

Even if you do not plan to invest into ambitiously complex hard disk subsystems, it is a good idea to configure multiple storage groups. Using separate backup sessions, it is possible to back up separate storage groups to different tape drives on remote computers in the network concurrently. This saves time and gives you the ability to perform parallel restores as well. To restore multiple storage groups concurrently, launch multiple restore sessions.

NOTE


It is not possible to backup or restore databases from a particular storage group in multiple restore sessions simultaneously. You may back them up or restore them individually in a series of sessions.

Maintaining Databases

Databases become fragmented over time in a normal process that you can't prevent, just as you can't prevent the fragmentation of a computer's hard disk. However, fragmentation slows down the server, which is not desirable, and significant database fragmentation can lead to database inconsistencies that may cause serious problems. Mailbox and public stores must therefore be maintained (defragmented) regularly.

Database Defragmentation

The Information Store defragments its databases automatically during scheduled maintenance cycles. Database inconsistencies may also be fixed during every startup and shutdown of the server in a process known as soft recovery. For that reason, you don't need to worry about database fragmentation too much. However, you might want to check the maintenance schedule, which can be defined in the Database tab of the corresponding store under Maintenance Interval. Maintenance processes should run at different times from backup operations.

Database Compaction

Online defragmentation does not reduce the size of the databases. Deleted objects are reordered and free space in the database files is marked as available. This is usually sufficient, but it may be desirable to shrink the database size to recover free disk space, for instance, if you have moved a large number of mailboxes away from a particular server. During its online defragmentation cycles, the Information Store will log an event in the application event log (Event ID 1221), which indicates the amount of available free database space. To give an example from the test environment: "The database 'First Storage Group\Mailbox Store (BLUESKY-SRV1)' has 4 megabytes of free space after online defragmentation has terminated."

To reduce the physical size of the database files, you need to use the database compaction tool (ESEUTIL.EXE). ESEUTIL.EXE is a very powerful low-level database utility that allows you to perform database consistency checks, defragmentation, and failure correction at the level of the ESE. If a store is mounted while you try to use ESEUTIL.EXE to compact its databases, the error code -1032 (JET_errFileAccessDenied) will be returned. ESEUTIL.EXE is a command-line utility that can be found in the \Program Files\Exchsrvr\Bin directory. For a complete list of command-line switches, type eseutil, and press Enter. Detailed information is also provided in a file called ESEUTIL.RTF, which can be found in the \Support\Utils directory on the Exchange 2000 Server CD. Do not forget to perform a full backup before compacting databases offline, just to be prepared in case ESEUTIL.EXE acts differently than expected.

IMPORTANT


Do not leave temporary database files on the Exchange 2000 server and perform an immediate full backup following a successful compaction.

Troubleshooting Database Problems

If you experience Information Store problems, you can use ESEUTIL.EXE with the /g switch to verify database integrity. If you discover a corrupted database, you may attempt to fix the problem. However, you should first reboot the server because soft recovery, which is launched during the server startup, might automatically correct the inconsistency. Likewise, if you have a recent backup available, you should not attempt to fix corruption manually. User data may be lost because the repair works this way: An integrity check is performed to find corrupted pages and their corresponding tables. ESEUTIL.EXE will attempt to repair corrupted tables, but pages (that is, data) that cannot be fixed are purged and can therefore no longer be found in the database.

If all your recent backups cannot be used, you will have to fix corruption using ESEUTIL.EXE with the /p switch. It is important to note that the repair is performed at the level of the ESE, which is below the Information Store. While corrupted pages are fixed and purged, the database is returned to a consistent state, but this does not mean that it still contains all the data that the Information Store needs to operate accurately. Hence, after running ESEUTIL.EXE, you must check the databases at the Information Store level using ISINTEG.EXE.

The Information Store Integrity utility (Isinteg) can find and eliminate database errors and problems in high-level data structures. ISINTEG.EXE can be found in the \Program Files\Exchsrvr\Bin directory. By default, this utility does not correct any corruption; it checks only for table damage, incorrect reference counters, and nonreferenced items. To fix problems, you must specify the -fix option at the command line. ISINTEG.EXE writes details about tests and correction processes to a log file.

CAUTION


If you have to work with ESEUTIL.EXE and ISINTEG.EXE to fix database corruption, it is advisable to contact Microsoft Product Support Services (MS PSS) for assistance. Before fixing any inconsistencies, always back up all databases. Be aware that you will most likely lose data during the repair. ESEUTIL.EXE and ISINTEG.EXE cannot replace correctly performed backups.

Copying Databases Using the Esefile Utility

It is important to note that low-level database tools, such as ESEUTIL.EXE, work with temporary database files. You need to make sure that you have sufficient free disk space on the machine where you want to perform the operation. As mentioned earlier, it is advantageous to reserve half of your database drives' capacity for maintenance and recovery purposes. If this is not feasible, consider copying the database files to another server with sufficient free disk space before working with ESEUTIL.EXE. It is possible to specify a temporary file on another drive if local disk space is low, but this significantly slows down the entire operation due to the additional copy process.

To copy large database files, use ESEFILE.EXE, which is located in the \Support\Utils\i386 directory on your Exchange 2000 Server CD. ESEFILE.EXE with /C <source> <destination> parameter can copy database files larger then 192 GB. ESEFILE.EXE is available in both the Standard and Enterprise Editions of Exchange 2000 Server. You can find more information about the Esefile in README.DOC from the \Support\Utils directory.

Exercise 4: Compacting Exchange 2000 Server Databases

In this exercise you will perform an offline compaction of a mailbox store. You will also check whether the databases are still intact after the compaction has finished.

To view a multimedia demonstration that displays how to perform this procedure, run the EX4CH20.AVI files from the \Exercise_Information\Chapter20 folder on the Supplemental Course Materials CD.

Prerequisites

  • Restart BLUESKY-SRV1 and make sure it is operational.
  • Log on as Administrator to BLUESKY-SRV1.

To compact databases and check their integrity

  1. Launch Exchange System Manager from the Microsoft Exchange program group.
  2. Expand the First Administrative Group, then Servers, then BLUESKY-SRV1, then First Storage Group. Right-click Mailbox Store (BLUESKY-SRV1), and select Dismount Store.
  3. In the Mailbox Store (BLUESKY-SRV1) dialog box informing you that this store will no longer be available to the users, click Yes to dismount the store.
  4. Click Start, click Run, and in the Run dialog box, type cmd, and then click OK.
  5. At the Windows 2000 command prompt, type cd \Program Files\Exchsrvr\Bin and press Enter. If the path to your Exchange directory is different, be sure to enter the correct path in this and the following steps.
  6. At the command prompt type eseutil /d "c:\Program Files\Exchsrvr\Mdbdata\priv1.edb" /t "c:\mbxstoredfrg.edb" /p and press Enter. This command line will cause ESEUTIL.EXE to compact the databases in temporary files called MBXSTOREDFRG.EDB and MBXSTOREDFRG.STM, which will be created and preserved in the root directory (see Figure 20.8).
  7. At the command prompt type eseutil /g "c:\mbxstoredfrg.edb" and press Enter to launch the database integrity check. Verify that ESEUTIL.EXE does not report any errors.
  8. At the command prompt type copy "c:\mbxstoredfrg.edb" "c:\Program Files\Exchsrvr\Mdbdata\priv1.edb" /y and press Enter to copy the compacted database over the production database.
  9. At the command prompt type copy "c:\mbxstoredfrg.stm" "c:\Program Files\Exchsrvr\Mdbdata\priv1.stm" /y and press Enter to copy the compacted streaming database over the production streaming database.
  10. At the command prompt type del "c:\mbxstoredfrg.*" and press Enter to delete the temporary database files.
  11. At the command prompt type isinteg -s bluesky-srv1 -test allfoldertests and press Enter to perform a folder group test.
  12. ISINTEG.EXE will inform you that only databases marked as offline can be checked. Make sure that the Mailbox Store (BLUESKY-SRV1) is marked as offline, type its corresponding storage number, and then press Enter.
  13. ISINTEG.EXE will inform you that you have selected the databases of First Storage Group / Mailbox Store (BLUESKY-SRV1). Type y and press Enter to launch the check (see Figure 20.8).
  14. Verify that ISINTEG.EXE returns no errors or warnings, and then close the command prompt.
  15. Switch back to Exchange System Manager, right-click Mailbox Store (BLUESKY-SRV1), and select Mount Store.
  16. In the Mailbox Store (BLUESKY-SRV1) dialog box, informing you that the store was mounted successfully, click OK.

    click to view at full size

    Figure 20.8 Compacting and checking a mailbox store

Exercise Summary

To launch a database compaction, start Eseutil with the /d switch, and specify the complete path to and the name of the desired Exchange database. The corresponding streaming database will be compacted as well (the /i command-line switch excludes the .stm file). ESEUTIL.EXE will read page after page from the original databases and copy them into temporary files. At successful completion, the temporary files are copied over the original databases. You may want to preserve the original databases by specifying the /p command-line switch, which disables the copy process. This allows you to check the compaction results and manually replace the store databases. To perform a high-level database check, use ISINTEG.EXE and specify an appropriate test routine.



MCSE Training Kit Exam 70-224(c) Microsoft Exchange 2000 Server Implementation and Administration
MCSE Training Kit Exam 70-224(c) Microsoft Exchange 2000 Server Implementation and Administration
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 186

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net