[rhmessaging-commits] rhmessaging commits: r2649 - in store/trunk/cpp: lib/jrnl and 1 other directories.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Fri Oct 17 13:51:24 EDT 2008


Author: kpvdr
Date: 2008-10-17 13:51:24 -0400 (Fri, 17 Oct 2008)
New Revision: 2649

Modified:
   store/trunk/cpp/lib/JournalImpl.cpp
   store/trunk/cpp/lib/jrnl/jcntl.cpp
   store/trunk/cpp/lib/jrnl/jcntl.hpp
   store/trunk/cpp/lib/jrnl/jerrno.cpp
   store/trunk/cpp/lib/jrnl/jerrno.hpp
   store/trunk/cpp/lib/jrnl/jinf.cpp
   store/trunk/cpp/lib/jrnl/jinf.hpp
   store/trunk/cpp/lib/jrnl/lfmgr.cpp
   store/trunk/cpp/lib/jrnl/lfmgr.hpp
   store/trunk/cpp/lib/jrnl/rcvdat.hpp
   store/trunk/cpp/lib/jrnl/rrfc.cpp
   store/trunk/cpp/lib/jrnl/wrfc.cpp
   store/trunk/cpp/tests/jrnl/_st_helper_fns.hpp
   store/trunk/cpp/tests/jrnl/_ut_jdir.cpp
   store/trunk/cpp/tests/jrnl/_ut_jinf.cpp
   store/trunk/cpp/tests/jrnl/_ut_lfmgr.cpp
Log:
Added auto-expand management functionality to class lfmgr. Added tests for all auto-expand functionality into _ut_lfmgr.

Modified: store/trunk/cpp/lib/JournalImpl.cpp
===================================================================
--- store/trunk/cpp/lib/JournalImpl.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/JournalImpl.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -144,9 +144,9 @@
 
     if (_mgmtObject != 0)
     {
-        _mgmtObject->set_initialFileCount(_lfmgr.size());
+        _mgmtObject->set_initialFileCount(_lfmgr.num_jfiles());
         _mgmtObject->set_dataFileSize(_jfsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
-        _mgmtObject->set_currentFileCount(_lfmgr.size());
+        _mgmtObject->set_currentFileCount(_lfmgr.num_jfiles());
         _mgmtObject->set_writePageSize(wcache_pgsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
         _mgmtObject->set_writePages(wcache_num_pages);
     }
@@ -172,9 +172,9 @@
 
     if (_mgmtObject != 0)
     {
-        _mgmtObject->set_initialFileCount(_lfmgr.size());
+        _mgmtObject->set_initialFileCount(_lfmgr.num_jfiles());
         _mgmtObject->set_dataFileSize(_jfsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
-        _mgmtObject->set_currentFileCount(_lfmgr.size());
+        _mgmtObject->set_currentFileCount(_lfmgr.num_jfiles());
         _mgmtObject->set_writePageSize(wcache_pgsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE);
         _mgmtObject->set_writePages(wcache_num_pages);
     }

Modified: store/trunk/cpp/lib/jrnl/jcntl.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jcntl.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/jcntl.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -112,7 +112,7 @@
 
     // Clear any existing journal files
     _jdir.clear_dir();
-    _lfmgr.initialize(num_jfiles, this, &new_fcntl);
+    _lfmgr.initialize(num_jfiles, false, 0, this, &new_fcntl);
 
     _wrfc.initialize(_jfsize_sblks);
     _rrfc.initialize();
@@ -154,7 +154,7 @@
 
     // Verify journal dir and journal files
     _jdir.verify_dir();
-    _rcvdat.reset(num_jfiles);
+    _rcvdat.reset(num_jfiles, false, 0);
 
     rcvr_janalyze(_rcvdat, prep_txn_list_ptr);
     highest_rid = _rcvdat._h_rid;
@@ -180,7 +180,7 @@
 {
     if (!_readonly_flag)
         throw jexception(jerrno::JERR_JCNTL_NOTRECOVERED, "jcntl", "recover_complete");
-    for (u_int16_t i=0; i<_lfmgr.size(); i++)
+    for (u_int16_t i=0; i<_lfmgr.num_jfiles(); i++)
         _lfmgr.get_fcntlp(i)->reset(&_rcvdat);
     _wrfc.initialize(_jfsize_sblks, &_rcvdat);
     _rrfc.initialize();
@@ -387,7 +387,7 @@
     u_int16_t fid = _wrfc.index();
     while ( _emap.get_enq_cnt(ffid) == 0 && _tmap.get_txn_fid_cnt(ffid) == 0 && ffid != fid)
     {
-        if (++ffid >= _lfmgr.size())
+        if (++ffid >= _lfmgr.num_jfiles())
             ffid = 0; 
     }
     if (!_rrfc.is_active())
@@ -435,7 +435,7 @@
 }
 
 fcntl*
-jcntl::new_fcntl(jcntl* const jcp, const std::size_t lid, const std::size_t fid, const rcvdat* const rdp)
+jcntl::new_fcntl(jcntl* const jcp, const u_int16_t lid, const u_int16_t fid, const rcvdat* const rdp)
 {
     if (!jcp) return 0;
     std::ostringstream oss;
@@ -475,8 +475,8 @@
         oss << FORMAT_SYSERR(errno);
         throw jexception(jerrno::JERR__RTCLOCK, oss.str(), "jcntl", "write_infofile");
     }
-    jinf ji(_jid, _jdir.dirname(), _base_filename, _lfmgr.size(), _jfsize_sblks,
-            _wmgr.cache_pgsize_sblks(), _wmgr.cache_num_pages(), ts);
+    jinf ji(_jid, _jdir.dirname(), _base_filename, _lfmgr.num_jfiles(), _lfmgr.is_ae(), _lfmgr.ae_max_jfiles(),
+            _jfsize_sblks, _wmgr.cache_pgsize_sblks(), _wmgr.cache_num_pages(), ts);
     ji.write();
 }
 
@@ -550,14 +550,14 @@
 
     // If the number of files does not tie up with the jinf file from the journal being recovered,
     // use the jinf data.
-    if (rd._num_jfiles != ji.num_jfiles())
+    if (rd._njf != ji.num_jfiles())
     {
         std::ostringstream oss;
         oss << "Recovery found " << ji.num_jfiles() <<
-                " files (different from --num-jfiles value of " << rd._num_jfiles << ").";
+                " files (different from --num-jfiles value of " << rd._njf << ").";
         this->log(LOG_WARN, oss.str());
-        rd._num_jfiles = ji.num_jfiles();
-        _rcvdat._enq_cnt_list.resize(rd._num_jfiles);
+        rd._njf = ji.num_jfiles();
+        _rcvdat._enq_cnt_list.resize(rd._njf);
     }
     if (_jfsize_sblks != ji.jfsize_sblks())
     {
@@ -627,7 +627,7 @@
         rd._lffull = rd._eo == (1 + _jfsize_sblks) * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE;
 
         // Check for journal full condition
-        u_int16_t next_wr_fid = (rd._lfid + 1) % rd._num_jfiles;
+        u_int16_t next_wr_fid = (rd._lfid + 1) % rd._njf;
         rd._jfull = rd._ffid == next_wr_fid && rd._enq_cnt_list[next_wr_fid];
     }
 }
@@ -851,7 +851,7 @@
             rd._eo = ifsp->tellg(); // remember file offset before closing
             assert(rd._eo != std::numeric_limits<std::size_t>::max()); // Check for error code -1
             ifsp->close();
-            if (++fid >= rd._num_jfiles)
+            if (++fid >= rd._njf)
             {
                 fid = 0;
                 lowi = !lowi; // Flip local owi
@@ -896,7 +896,7 @@
 {
     if (rd._ffid ? h.get_owi() == lowi : h.get_owi() != lowi) // Overwrite indicator changed
     {
-        u_int16_t expected_fid = rd._ffid ? rd._ffid - 1 : rd._num_jfiles - 1;
+        u_int16_t expected_fid = rd._ffid ? rd._ffid - 1 : rd._njf - 1;
         if (fid == expected_fid)
         {
             check_journal_alignment(fid, file_pos);

Modified: store/trunk/cpp/lib/jrnl/jcntl.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jcntl.hpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/jcntl.hpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -616,7 +616,7 @@
         */
         inline const std::string& base_filename() const { return _base_filename; }
 
-        inline u_int16_t num_jfiles() const { return _lfmgr.size(); }
+        inline u_int16_t num_jfiles() const { return _lfmgr.num_jfiles(); }
 
         inline fcntl* get_fcntlp(const u_int16_t fid) const { return _lfmgr.get_fcntlp(fid); }
 
@@ -637,8 +637,7 @@
         /**
         * /brief Static function for creating new fcntl objects for use with obj_arr.
         */
-        static fcntl* new_fcntl(jcntl* const jcp, const std::size_t lid, const std::size_t fid,
-                const rcvdat* const rdp);
+        static fcntl* new_fcntl(jcntl* const jcp, const u_int16_t lid, const u_int16_t fid, const rcvdat* const rdp);
 
     protected:
         /**

Modified: store/trunk/cpp/lib/jrnl/jerrno.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jerrno.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/jerrno.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -82,12 +82,17 @@
 const u_int32_t jerrno::JERR_FCNTL_CMPLOFFSOVFL = 0x0404;
 const u_int32_t jerrno::JERR_FCNTL_RDOFFSOVFL   = 0x0405;
 
+// class lfmgr
+const u_int32_t jerrno::JERR_LFMGR_BADAEFNUMLIM = 0x0500;
+const u_int32_t jerrno::JERR_LFMGR_AEFNUMLIMIT  = 0x0501;
+const u_int32_t jerrno::JERR_LFMGR_AEDISABLED   = 0x0502;
+
 // class rrfc
-const u_int32_t jerrno::JERR_RRFC_OPENRD        = 0x0500;
+const u_int32_t jerrno::JERR_RRFC_OPENRD        = 0x0600;
 
 // class jrec, enq_rec, deq_rec, txn_rec
-const u_int32_t jerrno::JERR_JREC_BADRECHDR     = 0x0600;
-const u_int32_t jerrno::JERR_JREC_BADRECTAIL    = 0x0601;
+const u_int32_t jerrno::JERR_JREC_BADRECHDR     = 0x0700;
+const u_int32_t jerrno::JERR_JREC_BADRECTAIL    = 0x0701;
 
 // class wmgr
 const u_int32_t jerrno::JERR_WMGR_BADPGSTATE    = 0x0801;
@@ -136,17 +141,12 @@
 
     // class jcntl
     _err_map[JERR_JCNTL_STOPPED] = "JERR_JCNTL_STOPPED: Operation on stopped journal.";
-    _err_map[JERR_JCNTL_READONLY] = "JERR_JCNTL_READONLY: "
-            "Write operation on read-only journal (during recovery).";
-    _err_map[JERR_JCNTL_AIOCMPLWAIT] = "JERR_JCNTL_AIOCMPLWAIT: "
-            "Timeout waiting for AIOs to complete.";
+    _err_map[JERR_JCNTL_READONLY] = "JERR_JCNTL_READONLY: Write operation on read-only journal (during recovery).";
+    _err_map[JERR_JCNTL_AIOCMPLWAIT] = "JERR_JCNTL_AIOCMPLWAIT: Timeout waiting for AIOs to complete.";
     _err_map[JERR_JCNTL_UNKNOWNMAGIC] = "JERR_JCNTL_UNKNOWNMAGIC: Found record with unknown magic.";
-    _err_map[JERR_JCNTL_NOTRECOVERED] = "JERR_JCNTL_NOTRECOVERED: "
-            "Operation requires recover() to be run first.";
-    _err_map[JERR_JCNTL_RECOVERJFULL] = "JERR_JCNTL_RECOVERJFULL: "
-            "Journal data files full, cannot write.";
-    _err_map[JERR_JCNTL_OWIMISMATCH] = "JERR_JCNTL_OWIMISMATCH: "
-            "Overwrite Indecator (OWI) change found in unexpected location.";
+    _err_map[JERR_JCNTL_NOTRECOVERED] = "JERR_JCNTL_NOTRECOVERED: Operation requires recover() to be run first.";
+    _err_map[JERR_JCNTL_RECOVERJFULL] = "JERR_JCNTL_RECOVERJFULL: Journal data files full, cannot write.";
+    _err_map[JERR_JCNTL_OWIMISMATCH] = "JERR_JCNTL_OWIMISMATCH: Overwrite Indecator (OWI) change found in unexpected location.";
 
     // class jdir
     _err_map[JERR_JDIR_NOTDIR] = "JERR_JDIR_NOTDIR: Directory name exists but is not a directory.";
@@ -165,13 +165,14 @@
     _err_map[JERR_FCNTL_OPENWR] = "JERR_FCNTL_OPENWR: Unable to open file for write.";
     _err_map[JERR_FCNTL_WRITE] = "JERR_FCNTL_WRITE: Unable to write to file.";
     _err_map[JERR_FCNTL_CLOSE] = "JERR_FCNTL_CLOSE: File close failed.";
-    _err_map[JERR_FCNTL_FILEOFFSOVFL] = "JERR_FCNTL_FILEOFFSOVFL: "
-            "Attempted increase file offset past file size.";
-    _err_map[JERR_FCNTL_CMPLOFFSOVFL] = "JERR_FCNTL_CMPLOFFSOVFL: "
-            "Attempted increase completed file offset past submitted offset.";
-    _err_map[JERR_FCNTL_RDOFFSOVFL] = "JERR_FCNTL_RDOFFSOVFL: "
-            "Attempted increase read offset past write offset.";
+    _err_map[JERR_FCNTL_FILEOFFSOVFL] = "JERR_FCNTL_FILEOFFSOVFL: Attempted increase file offset past file size.";
+    _err_map[JERR_FCNTL_CMPLOFFSOVFL] = "JERR_FCNTL_CMPLOFFSOVFL: Attempted increase completed file offset past submitted offset.";
+    _err_map[JERR_FCNTL_RDOFFSOVFL] = "JERR_FCNTL_RDOFFSOVFL: Attempted increase read offset past write offset.";
 
+    // class lfmgr
+    _err_map[JERR_LFMGR_BADAEFNUMLIM] = "JERR_LFMGR_BADAEFNUMLIM: Bad auto-expand file number limit.";
+    _err_map[JERR_LFMGR_AEFNUMLIMIT] = "JERR_LFMGR_AEFNUMLIMIT: Exceeded auto-expand file number limit.";
+    _err_map[JERR_LFMGR_AEDISABLED] = "JERR_LFMGR_AEDISABLED: Attempted to expand with auto-expand disabled.";
 
     // class rrfc
     _err_map[JERR_RRFC_OPENRD] = "JERR_RRFC_OPENRD: Unable to open file for read.";
@@ -181,43 +182,32 @@
     _err_map[JERR_JREC_BADRECTAIL] = "JERR_JREC_BADRECTAIL: Invalid data record tail.";
 
     // class wmgr
-    _err_map[JERR_WMGR_BADPGSTATE] = "JERR_WMGR_BADPGSTATE: "
-            "Page buffer in illegal state for operation.";
-    _err_map[JERR_WMGR_BADDTOKSTATE] = "JERR_WMGR_BADDTOKSTATE: "
-            "Data token in illegal state for operation.";
-    _err_map[JERR_WMGR_ENQDISCONT] = "JERR_WMGR_ENQDISCONT: "
-            "Enqueued new dtok when previous enqueue returned partly completed (state ENQ_PART).";
-    _err_map[JERR_WMGR_DEQDISCONT] = "JERR_WMGR_DEQDISCONT: "
-            "Dequeued new dtok when previous dequeue returned partly completed (state DEQ_PART).";
+    _err_map[JERR_WMGR_BADPGSTATE] = "JERR_WMGR_BADPGSTATE: Page buffer in illegal state for operation.";
+    _err_map[JERR_WMGR_BADDTOKSTATE] = "JERR_WMGR_BADDTOKSTATE: Data token in illegal state for operation.";
+    _err_map[JERR_WMGR_ENQDISCONT] = "JERR_WMGR_ENQDISCONT: Enqueued new dtok when previous enqueue returned partly completed (state ENQ_PART).";
+    _err_map[JERR_WMGR_DEQDISCONT] = "JERR_WMGR_DEQDISCONT: Dequeued new dtok when previous dequeue returned partly completed (state DEQ_PART).";
     _err_map[JERR_WMGR_DEQRIDNOTENQ] = "JERR_WMGR_DEQRIDNOTENQ: Dequeue rid is not enqueued.";
 
     // class rmgr
     _err_map[JERR_RMGR_UNKNOWNMAGIC] = "JERR_RMGR_UNKNOWNMAGIC: Found record with unknown magic.";
-    _err_map[JERR_RMGR_RIDMISMATCH] = "JERR_RMGR_RIDMISMATCH: "
-            "RID mismatch between current record and dtok RID";
+    _err_map[JERR_RMGR_RIDMISMATCH] = "JERR_RMGR_RIDMISMATCH: RID mismatch between current record and dtok RID";
     //_err_map[JERR_RMGR_FIDMISMATCH] = "JERR_RMGR_FIDMISMATCH: FID mismatch between emap and rrfc";
-    _err_map[JERR_RMGR_ENQSTATE] = "JERR_RMGR_ENQSTATE: "
-            "Attempted read when data token wstate was not ENQ";
-    _err_map[JERR_RMGR_BADRECTYPE] = "JERR_RMGR_BADRECTYPE: "
-            "Attempted operation on inappropriate record type";
+    _err_map[JERR_RMGR_ENQSTATE] = "JERR_RMGR_ENQSTATE: Attempted read when data token wstate was not ENQ";
+    _err_map[JERR_RMGR_BADRECTYPE] = "JERR_RMGR_BADRECTYPE: Attempted operation on inappropriate record type";
 
     // class data_tok
-    _err_map[JERR_DTOK_ILLEGALSTATE] = "JERR_MTOK_ILLEGALSTATE: "
-            "Attempted to change to illegal state.";
+    _err_map[JERR_DTOK_ILLEGALSTATE] = "JERR_MTOK_ILLEGALSTATE: Attempted to change to illegal state.";
     //_err_map[JERR_DTOK_RIDNOTSET] = "JERR_DTOK_RIDNOTSET: Record ID not set.";
 
     // class enq_map, txn_map
-    _err_map[JERR_MAP_DUPLICATE] = "JERR_MAP_DUPLICATE: "
-            "Attempted to insert record into map using duplicate key.";
+    _err_map[JERR_MAP_DUPLICATE] = "JERR_MAP_DUPLICATE: Attempted to insert record into map using duplicate key.";
     _err_map[JERR_MAP_NOTFOUND] = "JERR_MAP_NOTFOUND: Key not found in map.";
     _err_map[JERR_MAP_LOCKED] = "JERR_MAP_LOCKED: Record ID locked by a pending transaction.";
 
     // class jinf
-    _err_map[JERR_JINF_CVALIDFAIL] = "JERR_JINF_CVALIDFAIL: "
-            "Journal compatibility validation failure.";
+    _err_map[JERR_JINF_CVALIDFAIL] = "JERR_JINF_CVALIDFAIL: Journal compatibility validation failure.";
     _err_map[JERR_JINF_NOVALUESTR] = "JERR_JINF_NOVALUESTR: No value attribute found in jinf file.";
-    _err_map[JERR_JINF_BADVALUESTR] = "JERR_JINF_BADVALUESTR: "
-            "Bad format for value attribute in jinf file";
+    _err_map[JERR_JINF_BADVALUESTR] = "JERR_JINF_BADVALUESTR: Bad format for value attribute in jinf file";
     _err_map[JERR_JINF_JDATEMPTY] = "JERR_JINF_JDATEMPTY: Journal data files empty.";
     _err_map[JERR_JINF_TOOMANYFILES] = "JERR_JINF_TOOMANYFILES: Too many journal data files.";
 

Modified: store/trunk/cpp/lib/jrnl/jerrno.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jerrno.hpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/jerrno.hpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -100,6 +100,11 @@
         static const u_int32_t JERR_FCNTL_CMPLOFFSOVFL; ///< Increased cmpl offs past subm offs
         static const u_int32_t JERR_FCNTL_RDOFFSOVFL;   ///< Increased read offs past write offs
 
+        // class lfmgr
+        static const u_int32_t JERR_LFMGR_BADAEFNUMLIM; ///< Bad auto-expand file number limit
+        static const u_int32_t JERR_LFMGR_AEFNUMLIMIT;  ///< Exceeded auto-expand file number limit
+        static const u_int32_t JERR_LFMGR_AEDISABLED;   ///< Attempted to expand with auto-expand disabled
+
         // class rrfc
         static const u_int32_t JERR_RRFC_OPENRD;        ///< Unable to open file for read
 

Modified: store/trunk/cpp/lib/jrnl/jinf.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jinf.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/jinf.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -49,6 +49,8 @@
 jinf::jinf(const std::string& jinf_filename, bool validate_flag):
         _jver(0),
         _num_jfiles(0),
+        _ae(false),
+        _ae_max_jfiles(0),
         _jfsize_sblks(0),
         _sblk_size_dblks(0),
         _dblk_size(0),
@@ -67,8 +69,8 @@
         validate();
 }
 
-jinf::jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename,
-        const u_int16_t num_jfiles, const u_int32_t jfsize_sblks,
+jinf::jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename, const u_int16_t num_jfiles,
+        const bool auto_expand, const u_int16_t ae_max_jfiles, const u_int32_t jfsize_sblks,
         const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages, const timespec& ts):
         _jver(RHM_JDAT_VERSION),
         _jid(jid),
@@ -76,6 +78,8 @@
         _base_filename(base_filename),
         _ts(ts),
         _num_jfiles(num_jfiles),
+        _ae(auto_expand),
+        _ae_max_jfiles(ae_max_jfiles),
         _jfsize_sblks(jfsize_sblks),
         _sblk_size_dblks(JRNL_SBLK_SIZE),
         _dblk_size(JRNL_DBLK_SIZE),
@@ -115,6 +119,21 @@
         oss << "; maximum=" << JRNL_MAX_NUM_FILES << std::endl;
         err = true;
     }
+    if (_ae)
+    {
+        if (_ae_max_jfiles > _num_jfiles)
+        {
+            oss << "Number of journal files exceeds auto-expansion limit: found=" << _num_jfiles;
+            oss << "; maximum=" << _ae_max_jfiles;
+            err = true;
+        }
+        if (_ae_max_jfiles > JRNL_MAX_NUM_FILES)
+        {
+            oss << "Auto-expansion file limit too large: found=" << _ae_max_jfiles;
+            oss << "; maximum=" << JRNL_MAX_NUM_FILES;
+            err = true;
+        }
+    }
     if (_jfsize_sblks < JRNL_MIN_FILE_SIZE)
     {
         oss << "Journal file size too small: found=" << _jfsize_sblks;
@@ -271,7 +290,7 @@
     return _frot;
 }
 
-const std::string
+std::string
 jinf::to_string() const
 {
     std::ostringstream oss;
@@ -284,6 +303,8 @@
     oss << "  Journal base filename: \"" << _base_filename << "\"" << std::endl;
     oss << "  Journal version: " << (unsigned)_jver << std::endl;
     oss << "  Number of journal files: " << _num_jfiles << std::endl;
+    oss << "  Auto-expand mode: " << (_ae ? "enabled" : "disabled") << std::endl;
+    if (_ae) oss << "  Max. number of journal files (in auto-expand mode): " << _ae_max_jfiles << std::endl;
     oss << "  Journal file size: " << _jfsize_sblks << " sblks" << std::endl;
     oss << "  Softblock size (JRNL_SBLK_SIZE): " << _sblk_size_dblks << " dblks" << std::endl;
     oss << "  Datablock size (JRNL_DBLK_SIZE): " << _dblk_size << " bytes" << std::endl;
@@ -294,7 +315,7 @@
     return oss.str();
 }
 
-const std::string
+std::string
 jinf::xml_str() const
 {
     // TODO: This is *not* an XML writer, rather for simplicity, it uses literals. I'm sure a more elegant way can be
@@ -321,6 +342,8 @@
     oss << "  </creation_time>" << std::endl;
     oss << "  <journal_file_geometry>" << std::endl;
     oss << "    <number_jrnl_files value=\"" << _num_jfiles << "\" />" << std::endl;
+    oss << "    <auto_expand value=\"" << (_ae ? "true" : "false") << "\" />" << std::endl;
+    if (_ae) oss << "    <auto_expand_max_number_jrnl_files value=\"" << _ae_max_jfiles << "\" />" << std::endl;
     oss << "    <jrnl_file_size_sblks value=\"" << _jfsize_sblks << "\" />" << std::endl;
     oss << "    <JRNL_SBLK_SIZE value=\"" << _sblk_size_dblks << "\" />" << std::endl;
     oss << "    <JRNL_DBLK_SIZE value=\"" << _dblk_size << "\" />" << std::endl;
@@ -339,7 +362,8 @@
 jinf::read(const std::string& jinf_filename)
 {
     // TODO: This is *not* an XML reader, rather for simplicity, it is a brute-force line reader which relies on string
-    // recognition. Can it be replaced cheaply by the real thing?
+    // recognition. It relies on the format of xml_str() above; it will not handle a XML restructuring.
+    // *** Can it be replaced cheaply by a real XML reader? Should it be, or is this sufficient? ***
 
     char buff[1024]; // limit of line input length
     std::ifstream jinfs(jinf_filename.c_str());
@@ -358,6 +382,10 @@
             string_value(_base_filename, buff);
         else if(std::strstr(buff, "number_jrnl_files"))
             _num_jfiles = u_int16_value(buff);
+        else if(std::strstr(buff, "auto_expand"))
+            _ae = bool_value(buff);
+        else if(std::strstr(buff, "auto_expand_max_number_jrnl_files"))
+            _ae_max_jfiles = u_int16_value(buff);
         else if(std::strstr(buff, "jrnl_file_size_sblks"))
             _jfsize_sblks = u_int32_value(buff);
         else if(std::strstr(buff, "JRNL_SBLK_SIZE"))
@@ -383,6 +411,12 @@
     jinfs.close();
 }
 
+bool
+jinf::bool_value(char* line) const
+{
+    return std::strcmp(find_value(line), "true") == 0;
+}
+
 u_int16_t
 jinf::u_int16_value(char* line) const
 {
@@ -395,14 +429,14 @@
     return std::atol(find_value(line));
 }
 
-const std::string&
+std::string&
 jinf::string_value(std::string& str, char* line) const
 {
     str.assign(find_value(line));
     return str;
 }
 
-const char*
+char*
 jinf::find_value(char* line) const
 {
     const char* target1_str = "value=\"";

Modified: store/trunk/cpp/lib/jrnl/jinf.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jinf.hpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/jinf.hpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -58,6 +58,8 @@
         std::string _base_filename;
         timespec _ts;
         u_int16_t _num_jfiles;
+        bool _ae;
+        u_int32_t _ae_max_jfiles;
         u_int32_t _jfsize_sblks;
         u_int16_t _sblk_size_dblks;
         u_int32_t _dblk_size;
@@ -77,8 +79,8 @@
         jinf(const std::string& jinf_filename, bool validate_flag);
         // constructor for writing jinf file
         jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename,
-                const u_int16_t num_jfiles, const u_int32_t jfsize_sblks,
-                const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages,
+                const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles,
+                const u_int32_t jfsize_sblks, const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages,
                 const timespec& ts);
         virtual ~jinf();
 
@@ -94,6 +96,8 @@
         inline const timespec& ts() const { return _ts; }
         inline u_int16_t num_jfiles() const { return _num_jfiles; }
         u_int16_t incr_num_jfiles();
+        inline bool is_ae() const { return _ae; }
+        inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; }
         inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; }
         inline u_int16_t sblk_size_dblks() const { return _sblk_size_dblks; }
         inline u_int32_t dblk_size() const { return _dblk_size; }
@@ -108,15 +112,16 @@
         bool get_initial_owi();
         bool get_frot();
 
-        const std::string to_string() const;
-        const std::string xml_str() const;
+        std::string to_string() const;
+        std::string xml_str() const;
 
     private:
         void read(const std::string& jinf_filename);
+        bool bool_value(char* line) const;
         u_int16_t u_int16_value(char* line) const;
         u_int32_t u_int32_value(char* line) const;
-        const std::string& string_value(std::string& str, char* line) const;
-        const char* find_value(char* line) const;
+        std::string& string_value(std::string& str, char* line) const;
+        char* find_value(char* line) const;
     };
 
 } // namespace journal

Modified: store/trunk/cpp/lib/jrnl/lfmgr.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/lfmgr.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/lfmgr.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -32,13 +32,15 @@
 #include "jrnl/lfmgr.hpp"
 
 #include <cassert>
+#include <jrnl/jerrno.hpp>
+#include <jrnl/jexception.hpp>
 
 namespace mrg
 {
 namespace journal
 {
 
-lfmgr::lfmgr()
+lfmgr::lfmgr() : _ae(false), _ae_max_jfiles(0)
 {}
 
 lfmgr::~lfmgr()
@@ -47,85 +49,140 @@
 }
 
 void
-lfmgr::initialize(const std::size_t num_jfiles,
+lfmgr::initialize(const u_int16_t num_jfiles,
+                  const bool ae,
+                  const u_int16_t ae_max_jfiles,
                   jcntl* const jcp,
-                  fcntl* (new_obj_fn)(jcntl* const jcp,
-                                      const std::size_t lid,
-                                      const std::size_t fid,
-                                      const rcvdat* const rdp))
+                  new_obj_fn_ptr fp)
 {
+    assert(jcp != 0);
     finalize();
-    if (num_jfiles > 0)
+
+    // Validate params
+    if (ae && ae_max_jfiles > 0 && ae_max_jfiles <= num_jfiles)
     {
-        _fcntl_arr.reserve(2 * num_jfiles); // reserve some extra for possible add_obj() operations
-        append(jcp, new_obj_fn, num_jfiles);
+        std::ostringstream oss;
+        oss << "_ae_max_jfiles=" << _ae_max_jfiles << "; num_jfiles=" << num_jfiles;
+        throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM,  oss.str(), "lfmgr", "initialize");
     }
+    _ae = ae;
+    _ae_max_jfiles = ae_max_jfiles;
+
+    const std::size_t num_res_files = ae
+                                      ? (ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES)
+                                      : num_jfiles;
+    _fcntl_arr.reserve(num_res_files);
+    append(jcp, fp, num_jfiles);
 }
 
 void
 lfmgr::recover(const rcvdat& rd,
                jcntl* const jcp,
-               fcntl* (new_obj_fn)(jcntl* const jcp,
-                                   const std::size_t lid,
-                                   const std::size_t fid,
-                                   const rcvdat* const rdp))
+               new_obj_fn_ptr fp)
 {
+    assert(jcp != 0);
     finalize();
-    _fcntl_arr.reserve(2 * rd._num_jfiles); // reserve some extra for possible add_obj() operations
-    _fcntl_arr.assign(rd._num_jfiles, 0);
+
+    // Validate rd params
+    if (rd._aemjf > 0 && rd._aemjf <= rd._njf)
+    {
+        std::ostringstream oss;
+        oss << "_ae_max_jfiles=" << rd._aemjf << "; num_jfiles=" <<rd._njf ;
+        throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM,  oss.str(), "lfmgr", "recover");
+    }
+    _ae = rd._ae;
+    _ae_max_jfiles = rd._aemjf;
+
+    const std::size_t num_res_files = rd._ae
+                                      ? (rd._aemjf ? rd._aemjf : JRNL_MAX_NUM_FILES)
+                                      : rd._njf;
+    _fcntl_arr.reserve(num_res_files);
+    _fcntl_arr.assign(rd._njf, 0);
     std::vector<u_int16_t> lid_list(rd._fid_list.size(), 0);
     for (std::size_t lid = 0; lid < rd._fid_list.size(); lid++)
         lid_list[rd._fid_list[lid]] = lid;
-    // NOTE: rd._fid_list may be smaller than rd._num_jfiles (journal may be empty or not yet file-cycled)
-    for (std::size_t fid = 0; fid < rd._num_jfiles; fid++)
+    // NOTE: rd._fid_list may be smaller than rd._njf (journal may be empty or not yet file-cycled)
+    for (std::size_t fid = 0; fid < rd._njf; fid++)
         if (fid < rd._fid_list.size())
-            _fcntl_arr[lid_list[fid]] = new_obj_fn(jcp, lid_list[fid], fid, &rd);
+            _fcntl_arr[lid_list[fid]] = fp(jcp, lid_list[fid], fid, &rd);
         else
-            _fcntl_arr[fid] = new_obj_fn(jcp, fid, fid, &rd);
+            _fcntl_arr[fid] = fp(jcp, fid, fid, &rd);
 }
 
 void
-lfmgr::append(jcntl* const jcp,
-              fcntl* (new_obj_fn)(jcntl* const jcp,
-                                  const std::size_t lid,
-                                  const std::size_t fid,
-                                  const rcvdat* const rdp),
-              const std::size_t num_jfiles)
-{
-    std::size_t s = _fcntl_arr.size();
-    for (std::size_t i = s; i < s + num_jfiles; i++)
-        _fcntl_arr.push_back(new_obj_fn(jcp, i, i, 0));
-}
-
-void
-lfmgr::insert(const std::size_t after_index,
+lfmgr::insert(const u_int16_t after_index,
               jcntl* const jcp,
-              fcntl* (new_obj_fn)(jcntl* const jcp,
-                                  const std::size_t lid,
-                                  const std::size_t fid,
-                                  const rcvdat* const rdp),
-              const std::size_t num_jfiles)
+              new_obj_fn_ptr fp,
+              const u_int16_t num_jfiles)
 {
+    assert(jcp != 0);
     assert(after_index < _fcntl_arr.size());
+    if (!_ae) throw jexception(jerrno::JERR_LFMGR_AEDISABLED, "lfmgr", "insert");
+    if (num_jfiles == 0) return;
     std::size_t fid = _fcntl_arr.size();
+    const u_int16_t eff_ae_max_jfiles = _ae_max_jfiles ? _ae_max_jfiles : JRNL_MAX_NUM_FILES;
+    if (fid + num_jfiles > eff_ae_max_jfiles)
+    {
+        std::ostringstream oss;
+        oss << "num_files=" << fid << " incr=" << num_jfiles << " limit=" << _ae_max_jfiles;
+        throw jexception(jerrno::JERR_LFMGR_AEFNUMLIMIT, oss.str(), "lfmgr", "insert");
+    }
     for (std::size_t lid = after_index + 1; lid <= after_index + num_jfiles; lid++, fid++)
-        _fcntl_arr.insert(_fcntl_arr.begin() + lid, new_obj_fn(jcp, lid, fid, 0));
+        _fcntl_arr.insert(_fcntl_arr.begin() + lid, fp(jcp, lid, fid, 0));
     for (std::size_t lid = after_index + num_jfiles + 1; lid < _fcntl_arr.size(); lid++)
     {
-        fcntl* fp = _fcntl_arr[lid];
-        assert(fp != 0);
-        fp->set_lid(fp->lid() + num_jfiles);
+        fcntl* p = _fcntl_arr[lid];
+        assert(p != 0);
+        p->set_lid(p->lid() + num_jfiles);
     }
 }
 
 void
 lfmgr::finalize()
 {
-    for (u_int32_t i=0; i<_fcntl_arr.size(); i++)
+    for (u_int32_t i = 0; i < _fcntl_arr.size(); i++)
         delete _fcntl_arr[i];
     _fcntl_arr.clear();
+    _ae = false;
+    _ae_max_jfiles = 0;
 }
 
+void
+lfmgr::set_ae(const bool ae)
+{
+    if (ae && _ae_max_jfiles > 0 && _ae_max_jfiles <= _fcntl_arr.size())
+    {
+        std::ostringstream oss;
+        oss << "_ae_max_jfiles=" << _ae_max_jfiles << "; _fcntl_arr.size()=" << _fcntl_arr.size();
+        throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM, oss.str(), "lfmgr", "set_ae");
+    }
+    if (ae && _fcntl_arr.max_size() < _ae_max_jfiles)
+        _fcntl_arr.reserve(_ae_max_jfiles ? _ae_max_jfiles : JRNL_MAX_NUM_FILES);
+    _ae = ae;
+}
+
+void
+lfmgr::set_ae_max_jfiles(const u_int16_t ae_max_jfiles)
+{
+    if (_ae && ae_max_jfiles > 0 && ae_max_jfiles <= _fcntl_arr.size())
+    {
+        std::ostringstream oss;
+        oss << "_ae_max_jfiles=" << _ae_max_jfiles << "; _fcntl_arr.size()=" << _fcntl_arr.size();
+        throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM,  oss.str(), "lfmgr", "set_ae_max_jfiles");
+    }
+    if (_ae && _fcntl_arr.max_size() < ae_max_jfiles)
+        _fcntl_arr.reserve(ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES);
+    _ae_max_jfiles = ae_max_jfiles;
+}
+
+u_int16_t
+lfmgr::ae_jfiles_rem() const
+{
+    if (_ae_max_jfiles > _fcntl_arr.size()) return _ae_max_jfiles - _fcntl_arr.size();
+    if (_ae_max_jfiles == 0) return JRNL_MAX_NUM_FILES - _fcntl_arr.size();
+    return 0;
+}
+
 // Testing functions
 
 void
@@ -145,5 +202,23 @@
         lid_list[_fcntl_arr[i]->fid()] = i;
 }
 
+// === protected fns ===
+
+void
+lfmgr::append(jcntl* const jcp,
+              new_obj_fn_ptr fp,
+              const u_int16_t num_jfiles)
+{
+    std::size_t s = _fcntl_arr.size();
+    if (_ae_max_jfiles && s + num_jfiles > _ae_max_jfiles)
+    {
+        std::ostringstream oss;
+        oss << "num_files=" << s << " incr=" << num_jfiles << " limit=" << _ae_max_jfiles;
+        throw jexception(jerrno::JERR_LFMGR_AEFNUMLIMIT, oss.str(), "lfmgr", "append");
+    }
+    for (std::size_t i = s; i < s + num_jfiles; i++)
+        _fcntl_arr.push_back(fp(jcp, i, i, 0));
+}
+
 } // namespace journal
 } // namespace mrg

Modified: store/trunk/cpp/lib/jrnl/lfmgr.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/lfmgr.hpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/lfmgr.hpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -113,16 +113,35 @@
     *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
     * </pre>
     *
-    * There are two independent tests that may be made to resolve duplicat lids during recovery in such cases:
+    * There are two independent tests that may be made to resolve duplicate lids during recovery in such cases:
     * <ol>
     *   <li>The correct lid has owi flag that matches that of fid/lid 0</li>
     *   <li>The most recently inserted (hence correct) lid has fids that are higher than the duplicat that was not
     *       overwritten</li>
     * </ol>
+    *
+    * NOTE: NOT THREAD SAFE. Provide external thread protection if used in multi-threaded environments.
     */
     class lfmgr
     {
-    protected:
+    public:
+        /**
+        * \brief Function pointer to function that will create a new fcntl object and return its pointer.
+        *
+        * \param jcp        Pointer to jcntl instance from which journal file details will be obtained.
+        * \param lid        Logical ID for new fcntl instance.
+        * \param fid        Physical file ID for file associated with new fcntl instance.
+        * \param rdp        Pointer to rcvdat instance which conatins recovery information for new fcntl instance when
+        *                   recovering an existing file, or null if a new file is to be created.
+        */
+        typedef fcntl* (new_obj_fn_ptr)(jcntl* const jcp,
+                                        const u_int16_t lid,
+                                        const u_int16_t fid,
+                                        const rcvdat* const rdp);
+
+    private:
+        bool _ae;                       ///< Auto-expand mode
+        u_int16_t _ae_max_jfiles;       ///< Max file count for auto-expansion; 0 = no limit
         std::vector<fcntl*> _fcntl_arr; ///< Array of pointers to objects
 
     public:
@@ -135,17 +154,20 @@
         *
         * \param num_jfiles Number of files to be created, and consequently the number of fcntl objects in array
         *                   _fcntl_arr.
+        * \param ae         If true, allows auto-expansion; if false, disables auto-expansion.
+        * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current
+        *                   number of files. However, a zero value disables the limit checks, and allows unlimited
+        *                   expansion.
         * \param jcp        Pointer to jcntl instance. This is used to find the file path and base filename so that
         *                   new files may be created.
-        * \param new_obj_fn Pointer to function which creates and returns a pointer to a new fcntl object (and hence
+        * \param fp         Pointer to function which creates and returns a pointer to a new fcntl object (and hence
         *                   causes a new %journal file to be created).
         */
-        void initialize(const std::size_t num_jfiles,
+        void initialize(const u_int16_t num_jfiles,
+                        const bool ae,
+                        const u_int16_t ae_max_jfiles,
                         jcntl* const jcp,
-                        fcntl* (new_obj_fn)(jcntl* const jcp,
-                                            const std::size_t lid,
-                                            const std::size_t fid,
-                                            const rcvdat* const rdp));
+                        new_obj_fn_ptr fp);
 
         /**
         * \brief Initialize from a known lid-fid map fid_list, which is usually obtained from a recover. The index of
@@ -154,34 +176,14 @@
         * \param rd         Ref to rcvdat struct which contains recovery data.
         * \param jcp        Pointer to jcntl instance. This is used to find the file path and base filename so that
         *                   new files may be created.
-        * \param new_obj_fn Pointer to function which creates and returns a pointer to a new fcntl object (and hence
+        * \param fp         Pointer to function which creates and returns a pointer to a new fcntl object (and hence
         *                   causes a new %journal file to be created).
         */
         void recover(const rcvdat& rd,
                      jcntl* const jcp,
-                     fcntl* (new_obj_fn)(jcntl* const jcp,
-                                         const std::size_t lid,
-                                         const std::size_t fid,
-                                         const rcvdat* const rdp));
+                     new_obj_fn_ptr fp);
 
         /**
-        * \brief Append num_jfiles files to the end of the logical and file id sequence. This is similar to extending
-        * the from-scratch initialization.
-        *
-        * \param jcp        Pointer to jcntl instance. This is used to find the file path and base filename so that
-        *                   new files may be created.
-        * \param new_obj_fn Pointer to function which creates and returns a pointer to a new fcntl object (and hence
-        *                   causes a new %journal file to be created).
-        * \param num_jfiles The number of files by which to increase.
-        */
-        void append(jcntl* const jcp,
-                    fcntl* (new_obj_fn)(jcntl* const jcp,
-                                        const std::size_t lid,
-                                        const std::size_t fid,
-                                        const rcvdat* const rdp),
-                    const std::size_t num_jfiles = 1);
-
-        /**
         * \brief Insert num_jfiles files after lid index after_index. This causes all lids after after_index to be
         * increased by num_jfiles.
         *
@@ -191,17 +193,14 @@
         * \param after_index Lid index after which to insert file(s).
         * \param jcp        Pointer to jcntl instance. This is used to find the file path and base filename so that
         *                   new files may be created.
-        * \param new_obj_fn Pointer to function which creates and returns a pointer to a new fcntl object (and hence
+        * \param fp         Pointer to function which creates and returns a pointer to a new fcntl object (and hence
         *                   causes a new %journal file to be created).
         * \param num_jfiles The number of files by which to increase.
         */
-        void insert(const std::size_t after_index,
+        void insert(const u_int16_t after_index,
                     jcntl* const jcp,
-                    fcntl* (new_obj_fn)(jcntl* const jcp,
-                                        const std::size_t lid,
-                                        const std::size_t fid,
-                                        const rcvdat* const rdp),
-                    const std::size_t num_jfiles = 1);
+                    new_obj_fn_ptr fp,
+                    const u_int16_t num_jfiles = 1);
 
         /**
         * \brief Clears _fcntl_arr and deletes all fcntl instances.
@@ -213,23 +212,62 @@
         * either initialize() is called; thereafter true until finalize() is called, whereupon it will
         * return false again.
         *
-        * \return True if initialized; False otherwise.
+        * \return True if initialized; false otherwise.
         */
         inline bool is_init() const { return _fcntl_arr.size() > 0; }
 
         /**
+        * \brief Returns true if auto-expand mode is enabled; false if not.
+        *
+        * \return True if auto-expand mode is enabled; false if not.
+        */
+        inline bool is_ae() const { return _ae; }
+
+        /**
+        * \brief Sets the auto-expand mode to enabled if ae is true, to disabled otherwise. The value of _ae_max_jfiles
+        * must be valid to succeed (i.e. _ae_max_jfiles must be greater than the current number of files or be zero).
+        *
+        * \param ae         If true will enable auto-expand mode; if false will disable it.
+        */
+        void set_ae(const bool ae);
+
+        /**
         * \brief Returns the number of %journal files, including any that were appended or inserted since
         * initialization.
         *
         * \return Number of %journal files if initialized; 0 otherwise.
         */
-        inline std::size_t size() const { return _fcntl_arr.size(); }
+        inline u_int16_t num_jfiles() const { return static_cast<u_int16_t>(_fcntl_arr.size()); }
 
         /**
+        * \brief Returns the maximum number of files allowed for auto-expansion.
+        *
+        * \return Maximum number of files allowed for auto-expansion. A zero value represents a disabled limit
+        *   - i.e. unlimited expansion.
+        */
+        inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; }
+
+        /**
+        * \brief Sets the maximum number of files allowed for auto-expansion. A zero value disables the limit.
+        *
+        * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current
+        *                   number of files. However, a zero value disables the limit checks, and allows unlimited
+        *                   expansion.
+        */
+        void set_ae_max_jfiles(const u_int16_t ae_max_jfiles);
+
+        /**
+        * \brief Calculates the number of future files available for auto-expansion.
+        *
+        * \return The number of future files available for auto-expansion.
+        */
+        u_int16_t ae_jfiles_rem() const;
+
+        /**
         * \brief Get a pointer to fcntl instance for a given lid.
         *
-        * \return Pointer to fcntl object corresponding to logical id lid, or 0 if lid is out of range (greater than
-        * number of files in use).
+        * \return Pointer to fcntl object corresponding to logical id lid, or 0 if lid is out of range
+        *   (greater than number of files in use).
         */
         inline fcntl* get_fcntlp(const u_int16_t lid) const
                 { if (lid >= _fcntl_arr.size()) return 0; return _fcntl_arr[lid]; }
@@ -237,6 +275,23 @@
         // Testing functions
         void get_fid_list(std::vector<u_int16_t>& fid_list) const;
         void get_lid_list(std::vector<u_int16_t>& lid_list) const;
+
+    private:
+
+        /**
+        * \brief Append num_jfiles files to the end of the logical and file id sequence. This is similar to extending
+        * the from-scratch initialization.
+        *
+        * \param jcp        Pointer to jcntl instance. This is used to find the file path and base filename so that
+        *                   new files may be created.
+        * \param fp         Pointer to function which creates and returns a pointer to a new fcntl object (and hence
+        *                   causes a new %journal file to be created).
+        * \param num_jfiles The number of files by which to increase.
+        */
+        void append(jcntl* const jcp,
+                    new_obj_fn_ptr fp,
+                    const u_int16_t num_jfiles = 1);
+        
     };
 
 } // namespace journal

Modified: store/trunk/cpp/lib/jrnl/rcvdat.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/rcvdat.hpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/rcvdat.hpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -47,22 +47,26 @@
 
         struct rcvdat
         {
-            u_int16_t _num_jfiles;  ///< Number of journal files
-            bool _owi;              ///< Overwrite indicator
-            bool _frot;             ///< First rotation flag
-            bool _jempty;           ///< Journal data files empty
-            u_int16_t _ffid;        ///< First file id
-            std::size_t _fro;       ///< First record offset in ffid
-            u_int16_t _lfid;        ///< Last file id
-            std::size_t _eo;        ///< End offset (first byte past last record)
-            u_int64_t _h_rid;       ///< Highest rid found
-            bool _lffull;           ///< Last file is full
-            bool _jfull;            ///< Journal is full
+            u_int16_t _njf;     ///< Number of journal files
+            bool _ae;           ///< Auto-expand mode
+            u_int16_t _aemjf;   ///< Auto-expand mode max journal files
+            bool _owi;          ///< Overwrite indicator
+            bool _frot;         ///< First rotation flag
+            bool _jempty;       ///< Journal data files empty
+            u_int16_t _ffid;    ///< First file id
+            std::size_t _fro;   ///< First record offset in ffid
+            u_int16_t _lfid;    ///< Last file id
+            std::size_t _eo;    ///< End offset (first byte past last record)
+            u_int64_t _h_rid;   ///< Highest rid found
+            bool _lffull;       ///< Last file is full
+            bool _jfull;        ///< Journal is full
             std::vector<u_int16_t> _fid_list; ///< Fid-lid mapping - list of fids in order of lid
             std::vector<u_int32_t> _enq_cnt_list; ///< Number enqueued records found for each file
 
             rcvdat():
-                    _num_jfiles(0),
+                    _njf(0),
+                    _ae(false),
+                    _aemjf(0),
                     _owi(false),
                     _frot(false),
                     _jempty(true),
@@ -77,9 +81,11 @@
                     _enq_cnt_list()
             {}
 
-            void reset(u_int16_t num_jfiles)
+            void reset(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles)
             {
-                _num_jfiles = num_jfiles;
+                _njf = num_jfiles;
+                _ae = auto_expand;
+                _aemjf = ae_max_jfiles;
                 _owi=false;
                 _frot = false;
                 _jempty=true;
@@ -101,17 +107,19 @@
                 u_int16_t index = _ffid;
                 while (index != _lfid && _enq_cnt_list[index] == 0)
                 {
-                    if (++index >= _num_jfiles)
+                    if (++index >= _njf)
                         index = 0;
                 }
                 return index;
             }
 
-            std::string to_string(std::string& jid)
+            std::string to_string(const std::string& jid)
             {
                 std::ostringstream oss;
                 oss << "Recover file analysis (jid=\"" << jid << "\"):" << std::endl;
-                oss << "  Number of journal files (_num_jfiles) = " << _num_jfiles << std::endl;
+                oss << "  Number of journal files (_njf) = " << _njf << std::endl;
+                oss << "  Auto-expand mode (_ae) = " << (_ae ? "TRUE" : "FALSE") << std::endl;
+                if (_ae) oss << "  Auto-expand mode max journal files (_aemjf) = " << _aemjf << std::endl;
                 oss << "  Overwrite indicator (_owi) = " << (_owi ? "TRUE" : "FALSE") << std::endl;
                 oss << "  First rotation (_frot) = " << (_frot ? "TRUE" : "FALSE") << std::endl;
                 oss << "  Journal empty (_jempty) = " << (_jempty ? "TRUE" : "FALSE") << std::endl;
@@ -138,12 +146,14 @@
                 return oss.str();
             }
 
-            std::string to_log(std::string& jid)
+            std::string to_log(const std::string& jid)
             {
                 std::ostringstream oss;
                 oss << "Recover file analysis (jid=\"" << jid << "\"):";
-                oss << " njf=" << _num_jfiles;
-                oss << " owi=" << (_owi ? "T" : "F");
+                oss << " njf=" << _njf;
+                oss << " ae=" << (_owi ? "T" : "F");
+                oss << " aemjf=" << _aemjf;
+                oss << " owi=" << (_ae ? "T" : "F");
                 oss << " frot=" << (_frot ? "T" : "F");
                 oss << " jempty=" << (_jempty ? "T" : "F");
                 oss << " ffid=" << _ffid;

Modified: store/trunk/cpp/lib/jrnl/rrfc.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/rrfc.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/rrfc.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -74,10 +74,10 @@
 iores
 rrfc::rotate()
 {
-    if (!_lfmp->size())
+    if (!_lfmp->num_jfiles())
         throw jexception(jerrno::JERR__NINIT, "rrfc", "rotate");
     u_int16_t next_fc_index = _fc_index + 1;
-    if (next_fc_index == _lfmp->size())
+    if (next_fc_index == _lfmp->num_jfiles())
         next_fc_index = 0;
     fcntl* next_fc = _lfmp->get_fcntlp(next_fc_index);
     _fc_index = next_fc_index;

Modified: store/trunk/cpp/lib/jrnl/wrfc.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/wrfc.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/lib/jrnl/wrfc.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -77,7 +77,7 @@
     }
     _fsize_sblks = fsize_sblks;
     _fsize_dblks = fsize_sblks * JRNL_SBLK_SIZE;
-    _enq_cap_offs_dblks = (u_int32_t)std::ceil(_fsize_dblks * _lfmp->size() * (100.0 - JRNL_ENQ_THRESHOLD) / 100);
+    _enq_cap_offs_dblks = (u_int32_t)std::ceil(_fsize_dblks * _lfmp->num_jfiles() * (100.0 - JRNL_ENQ_THRESHOLD) / 100);
     // Check the offset is at least one file; if not, make it so
     if (_enq_cap_offs_dblks < _fsize_dblks)
         _enq_cap_offs_dblks = _fsize_dblks;
@@ -85,10 +85,10 @@
 
 iores wrfc::rotate()
 {
-    if (!_lfmp->size())
+    if (!_lfmp->num_jfiles())
         throw jexception(jerrno::JERR__NINIT, "wrfc", "rotate");
     _fc_index++;
-    if (_fc_index == _lfmp->size())
+    if (_fc_index == _lfmp->num_jfiles())
     {
         _fc_index = 0;
         _owi = !_owi;
@@ -107,7 +107,7 @@
     if (_frot)
         return 0;
     u_int16_t next_index = _fc_index + 1;
-    if (next_index >= _lfmp->size())
+    if (next_index >= _lfmp->num_jfiles())
         next_index = 0;
     return next_index;
 }
@@ -129,7 +129,7 @@
         fwd_dblks -= fwd_dblks > _fsize_dblks ? _fsize_dblks : fwd_dblks;
         if (fwd_dblks)
         {
-            if (++findex == _lfmp->size())
+            if (++findex == _lfmp->num_jfiles())
                 findex = 0;
             fcp = _lfmp->get_fcntlp(findex);
         }

Modified: store/trunk/cpp/tests/jrnl/_st_helper_fns.hpp
===================================================================
--- store/trunk/cpp/tests/jrnl/_st_helper_fns.hpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/tests/jrnl/_st_helper_fns.hpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -68,8 +68,10 @@
         jcntl(jid, jdir, base_filename) {}
     virtual ~test_jrnl() {}
     void initialize(const u_int16_t num_jfiles, const u_int32_t jfsize_sblks)
-        { jcntl::initialize(num_jfiles, jfsize_sblks, JRNL_WMGR_DEF_PAGES, JRNL_WMGR_DEF_PAGE_SIZE,
-            0, &aio_wr_callback); }
+    {
+        jcntl::initialize(num_jfiles, jfsize_sblks, JRNL_WMGR_DEF_PAGES, JRNL_WMGR_DEF_PAGE_SIZE, 0, &aio_wr_callback);
+        _jdir.create_dir();
+    }
     void recover(const u_int16_t num_jfiles, const u_int32_t jfsize_sblks, vector<string>* txn_list,
             u_int64_t& highest_rid)
     { jcntl::recover(num_jfiles, jfsize_sblks, JRNL_WMGR_DEF_PAGES, JRNL_WMGR_DEF_PAGE_SIZE, 0,
@@ -226,6 +228,7 @@
                             const u_int16_t num_files = 1,  // Number of files to insert
                             const bool adjust_lids = true)  // Adjust lids following inserted files
         {
+            if (num_files == 0) return;
             _num_used_files += num_files;
             const u_int16_t num_jfiles_before_append = _map.size();
             lfmap_citr i = _map.find(after_lid);
@@ -375,9 +378,9 @@
         * header (512 bytes each) and a single jinf file which contains the journal metadata required for recovery
         * analysis.
         */
-        void write_journal()
+        void write_journal(const bool ae, const u_int16_t ae_max_jfiles)
         {
-            create_jinf();
+            create_jinf(ae, ae_max_jfiles);
             u_int16_t fid = 0;
             for (lfmap_citr itr = _map.begin(); itr != _map.end(); itr++, fid++)
             {
@@ -410,11 +413,11 @@
         * Method create_new_jinf(): This static call creates a default jinf file only. This is used to test the read
         * constructor of a jinf test object which reads a jinf file at instantiation.
         */
-        static void create_new_jinf(const string jid, const string base_filename)
+        static void create_new_jinf(const string jid, const string base_filename, const bool ae)
         {
             if (jdir::exists(test_dir))
                 jdir::delete_dir(test_dir);
-            create_jinf(NUM_JFILES, jid, base_filename);
+            create_jinf(NUM_JFILES, ae, (ae ? 5 * NUM_JFILES : 0), jid, base_filename);
         }
 
         /*
@@ -455,20 +458,21 @@
             fh._ts_nsec = ts.tv_nsec;
         }
 
-        void create_jinf()
+        void create_jinf(const bool ae, const u_int16_t ae_max_jfiles)
         {
             if (jdir::exists(test_dir))
                 jdir::delete_dir(test_dir);
-            create_jinf(_map.size(), _jid, _base_filename);
+            create_jinf(_map.size(), ae, ae_max_jfiles, _jid, _base_filename);
         }
 
-        static void create_jinf(u_int16_t num_files, const string jid, const string base_filename)
+        static void create_jinf(u_int16_t num_files, const bool ae, const u_int16_t ae_max_jfiles, const string jid,
+                const string base_filename)
         {
             jdir::create_dir(test_dir); // Check test dir exists; create it if not
             timespec ts;
             ::clock_gettime(CLOCK_REALTIME, &ts);
-            jinf ji(jid, test_dir, base_filename, num_files, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES,
-                    ts);
+            jinf ji(jid, test_dir, base_filename, num_files, ae, ae_max_jfiles, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE,
+                    JRNL_WMGR_DEF_PAGES, ts);
             ji.write();
         }
 

Modified: store/trunk/cpp/tests/jrnl/_ut_jdir.cpp
===================================================================
--- store/trunk/cpp/tests/jrnl/_ut_jdir.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/tests/jrnl/_ut_jdir.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -93,7 +93,7 @@
 {
     timespec ts;
     ::clock_gettime(CLOCK_REALTIME, &ts);
-    jinf ji("test journal id", dirname, base_filename, NUM_JFILES, JFSIZE_SBLKS,
+    jinf ji("test journal id", dirname, base_filename, NUM_JFILES, false, 0, JFSIZE_SBLKS,
             JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts);
     ji.write();
 }

Modified: store/trunk/cpp/tests/jrnl/_ut_jinf.cpp
===================================================================
--- store/trunk/cpp/tests/jrnl/_ut_jinf.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/tests/jrnl/_ut_jinf.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -52,7 +52,7 @@
     const string base_filename = test_name + "_bfn";
     jdir::create_dir(test_dir); // Check test dir exists; create it if not
     ::clock_gettime(CLOCK_REALTIME, &ts);
-    jinf ji(jid, test_dir, base_filename, NUM_JFILES, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts);
+    jinf ji(jid, test_dir, base_filename, NUM_JFILES, false, 0, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts);
     BOOST_CHECK_EQUAL(ji.jver(), RHM_JDAT_VERSION);
     BOOST_CHECK(ji.jid().compare(jid) == 0);
     BOOST_CHECK(ji.jdir().compare(test_dir) == 0);
@@ -61,6 +61,8 @@
     BOOST_CHECK_EQUAL(this_ts.tv_sec, ts.tv_sec);
     BOOST_CHECK_EQUAL(this_ts.tv_nsec, ts.tv_nsec);
     BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES));
+    BOOST_CHECK_EQUAL(ji.is_ae(), false);
+    BOOST_CHECK_EQUAL(ji.ae_max_jfiles(), u_int16_t(0));
     BOOST_CHECK_EQUAL(ji.jfsize_sblks(), u_int32_t(JFSIZE_SBLKS));
     BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), u_int16_t(JRNL_SBLK_SIZE));
     BOOST_CHECK_EQUAL(ji.dblk_size(), u_int32_t(JRNL_DBLK_SIZE));
@@ -77,7 +79,7 @@
     string test_name = get_test_name(test_filename, "read_constructor");
     const string jid = test_name + "_jid";
     const string base_filename = test_name + "_bfn";
-    lid_fid_map::create_new_jinf(jid, base_filename);
+    lid_fid_map::create_new_jinf(jid, base_filename, false);
 
     stringstream fn;
     fn << test_dir << "/" <<base_filename  << "." << JRNL_INFO_EXTENSION;
@@ -90,6 +92,8 @@
 //     BOOST_CHECK_EQUAL(this_ts.tv_sec, ts.tv_sec);
 //     BOOST_CHECK_EQUAL(this_ts.tv_nsec, ts.tv_nsec);
     BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES));
+    BOOST_CHECK_EQUAL(ji.is_ae(), false);
+    BOOST_CHECK_EQUAL(ji.ae_max_jfiles(), u_int16_t(0));
     BOOST_CHECK_EQUAL(ji.jfsize_sblks(), u_int32_t(JFSIZE_SBLKS));
     BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), u_int16_t(JRNL_SBLK_SIZE));
     BOOST_CHECK_EQUAL(ji.dblk_size(), u_int32_t(JRNL_DBLK_SIZE));
@@ -106,7 +110,7 @@
     string test_name = get_test_name(test_filename, "set_functions");
     const string jid = test_name + "_jid";
     const string base_filename = test_name + "_bfn";
-    lid_fid_map::create_new_jinf(jid, base_filename);
+    lid_fid_map::create_new_jinf(jid, base_filename, false);
 
     stringstream fn;
     fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -130,7 +134,7 @@
     string test_name = get_test_name(test_filename, "validate");
     const string jid = test_name + "_jid";
     const string base_filename = test_name + "_bfn";
-    lid_fid_map::create_new_jinf(jid, base_filename);
+    lid_fid_map::create_new_jinf(jid, base_filename, false);
 
     stringstream fn;
     fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -150,7 +154,7 @@
 
     lid_fid_map m(jid, base_filename);
     m.journal_create(NUM_JFILES, 0, 0);
-    m.write_journal();
+    m.write_journal(false, 0);
 
     stringstream fn;
     fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -175,7 +179,7 @@
     for (u_int16_t num_files = 1; num_files < NUM_JFILES; num_files++)
     {
         m.journal_create(NUM_JFILES, num_files, 0);
-        m.write_journal();
+        m.write_journal(false, 0);
 
         stringstream fn;
         fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -197,7 +201,7 @@
     for (u_int16_t file_num = 0; file_num < NUM_JFILES; file_num++)
     {
         m.journal_create(NUM_JFILES, NUM_JFILES, file_num);
-        m.write_journal();
+        m.write_journal(false, 0);
 
         stringstream fn;
         fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -222,7 +226,7 @@
             {
                 m.journal_create(NUM_JFILES, NUM_JFILES, oldest_lid);
                 m.journal_insert(after_lid, num_files);
-                m.write_journal();
+                m.write_journal(false, 0);
 
                 stringstream fn;
                 fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -253,7 +257,7 @@
             const u_int16_t after_lid = u_int16_t(m.size() * ::drand48());
             m.journal_insert(after_lid, num_files);
         }
-        m.write_journal();
+        m.write_journal(false, 0);
 
         stringstream fn;
         fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
@@ -293,7 +297,7 @@
             const u_int16_t num_files = u_int16_t(1 + (NUM_JFILES * ::drand48()));
             const u_int16_t after_lid = oldest_lid == 0 ? m.size() - 1 : oldest_lid - 1;
             m.journal_insert(after_lid, num_files, false);
-            m.write_journal();
+            m.write_journal(false, 0);
 
             stringstream fn;
             fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;

Modified: store/trunk/cpp/tests/jrnl/_ut_lfmgr.cpp
===================================================================
--- store/trunk/cpp/tests/jrnl/_ut_lfmgr.cpp	2008-10-17 17:28:47 UTC (rev 2648)
+++ store/trunk/cpp/tests/jrnl/_ut_lfmgr.cpp	2008-10-17 17:51:24 UTC (rev 2649)
@@ -82,25 +82,271 @@
         linear_vectors_equal(lm, fid_lid_size, res, false);
     }
 
-    static void rcvdat_init(rcvdat& rd, const u_int16_t num_jfiles, const u_int16_t fids[])
+    static void rcvdat_init(rcvdat& rd, const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles,
+        const u_int16_t fids[])
     {
-        rd.reset(num_jfiles);
+        rd.reset(num_jfiles, ae, ae_max_jfiles);
         load_vector(fids, num_jfiles, rd._fid_list);
         rd._jempty = false;
         rd._lfid = fids[num_jfiles - 1];
         rd._eo = 100 * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE;
     }
 
-    static void rcvdat_init(rcvdat& rd, const flist& fidl)
+    static void rcvdat_init(rcvdat& rd, const flist& fidl, const bool ae, const u_int16_t ae_max_jfiles)
     {
         const u_int16_t num_jfiles = fidl.size();
-        rd.reset(num_jfiles);
+        rd.reset(num_jfiles, ae, ae_max_jfiles);
         load_vector(fidl, rd._fid_list);
         rd._jempty = false;
         rd._lfid = fidl[num_jfiles - 1];
         rd._eo = 100 * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE;
     }
 
+    static void initialize(lfmgr& lm, test_jrnl& jc, const u_int16_t num_jfiles, const bool ae,
+            const u_int16_t ae_max_jfiles)
+    {
+        lm.initialize(num_jfiles, ae, ae_max_jfiles, &jc, &jc.new_fcntl);
+        BOOST_CHECK_EQUAL(lm.is_init(), true);
+        BOOST_CHECK_EQUAL(lm.is_ae(), ae);
+        BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles);
+        BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles);
+        if (num_jfiles)
+            check_linear_fids_lids(lm, num_jfiles);
+        else
+            BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
+    }
+
+    // version which sets up the lid_fid_map for later manipulation by insert tests
+    static void initialize(lid_fid_map& lfm, lfmgr& lm, test_jrnl& jc, const u_int16_t num_jfiles, const bool ae,
+            const u_int16_t ae_max_jfiles)
+    {
+        lfm.journal_create(num_jfiles, num_jfiles);
+        initialize(lm, jc, num_jfiles, ae, ae_max_jfiles);
+    }
+
+    static void prepare_recover(lid_fid_map& lfm, const u_int16_t size)
+    {
+        if (size < 4) BOOST_FAIL("prepare_recover(): size parameter (" << size << ") too small.");
+        lfm.journal_create(4, 4); // initial journal of size 4
+        u_int16_t s = 4; // cumulative size
+        while (s < size)
+        {
+            const u_int16_t ins_posn = u_int16_t(s * ::drand48()); // this insert posn
+            if (3.0 * ::drand48() > 1.0 || size - s < 2) // 2:1 chance of single insert when >= 2 still to insert
+            {
+                lfm.journal_insert(ins_posn); // single insert
+                s++;
+            }
+            else
+            {
+                // multiple insert, either 2 - 5
+                const u_int16_t max_ins_size = size - s >5 ? 5 : size - s;
+                const u_int16_t ins_size = 2 + u_int16_t((max_ins_size - 2) * ::drand48()); // this insert size
+                lfm.journal_insert(ins_posn, ins_size);
+                s += ins_size;
+            }
+        }
+    }
+
+    static void recover(lid_fid_map& lfm, lfmgr& lm, test_jrnl& jc, const bool ae, const u_int16_t ae_max_jfiles)
+    {
+        flist fidl;
+        flist lidl;
+        rcvdat rd;
+        const u_int16_t num_jfiles = lfm.size();
+
+        lfm.get_fid_list(fidl);
+        lfm.get_lid_list(lidl);
+        lfm.write_journal(ae, ae_max_jfiles);
+
+        lfmgr_test_helper::rcvdat_init(rd, fidl, ae, ae_max_jfiles);
+        lm.recover(rd, &jc, &jc.new_fcntl);
+        BOOST_CHECK_EQUAL(lm.is_init(), true);
+        BOOST_CHECK_EQUAL(lm.is_ae(), ae);
+        BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles);
+        BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles);
+        if (num_jfiles)
+            check_fids_lids(lm, fidl, lidl);
+        else
+            BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
+    }
+
+    static void finalize(lfmgr& lm)
+    {
+        lm.finalize();
+        BOOST_CHECK_EQUAL(lm.is_init(), false);
+        BOOST_CHECK_EQUAL(lm.is_ae(), false);
+        BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), u_int16_t(0));
+        BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0));
+        BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
+        vector<u_int16_t> res;
+        lm.get_fid_list(res);
+        BOOST_CHECK_EQUAL(res.size(), u_int16_t(0));
+        lm.get_lid_list(res);
+        BOOST_CHECK_EQUAL(res.size(), u_int16_t(0));
+    }
+
+    static void insert(lid_fid_map& lfm, lfmgr& lm, test_jrnl& jc, const u_int16_t after_lid, const u_int16_t incr = 1)
+    {
+        flist fidl;
+        flist lidl;
+        const u_int16_t num_jfiles = lm.num_jfiles();
+        lfm.journal_insert(after_lid, incr);
+        lfm.get_fid_list(fidl);
+        lfm.get_lid_list(lidl);
+        lm.insert(after_lid, &jc, &jc.new_fcntl, incr);
+        BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles + incr);
+        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+    }
+
+    static void check_ae_max_jfiles(lfmgr& lm, const u_int16_t num_jfiles, const u_int16_t ae_max_jfiles)
+    {
+        bool legal = ae_max_jfiles > num_jfiles || ae_max_jfiles == 0;
+
+        lm.set_ae(false);
+        BOOST_CHECK(!lm.is_ae());
+        if (legal)
+        {
+            lm.set_ae_max_jfiles(ae_max_jfiles);
+            BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles);
+            lm.set_ae(true);
+            BOOST_CHECK(lm.is_ae());
+            BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), ae_max_jfiles
+                                                  ? ae_max_jfiles - num_jfiles
+                                                  : JRNL_MAX_NUM_FILES - num_jfiles);
+        }
+        else
+        {
+            lm.set_ae_max_jfiles(ae_max_jfiles);
+            BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles);
+            try
+            {
+                lm.set_ae(true); // should raise exception
+                BOOST_ERROR("Auto-expand enabled with out-of-range ae_max_jfiles");
+            }
+            catch (const jexception& e) { BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_BADAEFNUMLIM); }
+            BOOST_CHECK(!lm.is_ae());
+            BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), 0);
+        }
+        BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles);
+    }
+
+    static void check_multiple_initialization_recover(lid_fid_map& lfm, test_jrnl& jc,
+            const u_int16_t num_jfiles_arr[][2], const bool init_flag_0, const bool finalize_flag,
+            const bool init_flag_1)
+    {
+        unsigned i_njf = 0;
+        while (num_jfiles_arr[i_njf][0] && num_jfiles_arr[i_njf][1])
+        {
+            for (unsigned i1_njf = 0; i1_njf <= 1; i1_njf++)
+            {
+                const u_int16_t num_jfiles_0 = num_jfiles_arr[i_njf][i1_njf == 0];
+                const u_int16_t num_jfiles_1 = num_jfiles_arr[i_njf][i1_njf != 0];
+
+                for (unsigned i_ae = 0; i_ae < 4; i_ae++)
+                {
+                    const bool ae_0 = i_ae & 0x1;
+                    const bool ae_1 = i_ae & 0x2;
+                    for (unsigned i_aemjf = 0; i_aemjf < 4; i_aemjf++)
+                    {
+                        const u_int16_t ae_max_jfiles_0 = i_aemjf & 0x1 ? 3 * num_jfiles_0 : 0;
+                        const u_int16_t ae_max_jfiles_1 = i_aemjf & 0x2 ? 4 * num_jfiles_1 : 0;
+
+                        lfmgr lm;
+
+                        if (init_flag_0)
+                            initialize(lm, jc, num_jfiles_0, ae_0, ae_max_jfiles_0);
+                        else
+                        {
+                            prepare_recover(lfm, num_jfiles_0);
+                            recover(lfm, lm, jc, ae_1, ae_max_jfiles_0);
+                            lfm.destroy_journal();
+                        }
+
+                        if (finalize_flag) finalize(lm);
+
+                        if (init_flag_1)
+                            initialize(lm, jc, num_jfiles_1, ae_1, ae_max_jfiles_1);
+                        else
+                        {
+                            prepare_recover(lfm, num_jfiles_1);
+                            recover(lfm, lm, jc, ae_1, ae_max_jfiles_1);
+                            lfm.destroy_journal();
+                        }
+                    }
+                }
+            }
+            i_njf++;
+        }
+    }
+
+    static void check_insert(lid_fid_map& lfm, lfmgr& lm, test_jrnl& jc, const u_int16_t after_lid,
+            const u_int16_t incr = 1)
+    {
+        const u_int16_t num_jfiles = lm.num_jfiles();
+        const u_int16_t ae_max_jfiles = lm.ae_max_jfiles();
+        const u_int16_t effective_ae_max_jfiles = ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES;
+        BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles);
+        bool legal = lm.is_ae() && num_jfiles + incr <= effective_ae_max_jfiles;
+        if (legal)
+        {
+            insert(lfm, lm, jc, after_lid, incr);
+            BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles + incr);
+            BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles - incr);
+        }
+        else
+        {
+            try
+            {
+                insert(lfm, lm, jc, after_lid, incr);
+                if (lm.is_ae())
+                    BOOST_ERROR("lfmgr::insert() succeeded and exceeded limit");
+                else
+                    BOOST_ERROR("lfmgr::insert() succeeded with auto-expand disabled");
+            }
+            catch (const jexception& e)
+            {
+                if (lm.is_ae())
+                    BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEFNUMLIMIT);
+                else
+                    BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEDISABLED);
+            }
+            BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles);
+            BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles);
+        }
+    }
+
+    static void check_limit(lid_fid_map& lfm, test_jrnl& jc, const bool ae, const u_int16_t num_jfiles,
+            const u_int16_t ae_max_jfiles)
+    {
+        lfmgr lm;
+        
+        for (unsigned i = 0; i < 2; i++)
+        {
+            if (i)
+                initialize(lfm, lm, jc, num_jfiles, ae, ae_max_jfiles);
+            else
+            {
+                prepare_recover(lfm, num_jfiles);
+                recover(lfm, lm, jc, ae, ae_max_jfiles);
+            }
+
+            // use up all available files
+            unsigned j = ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES;
+            while (ae && j > num_jfiles)
+            {
+                const u_int16_t posn = (lm.num_jfiles() - 1) * ::drand48();
+                const u_int16_t incr = 1 + (lm.ae_jfiles_rem() > 4 ? 3 : lm.ae_jfiles_rem() - 1) * ::drand48();
+                check_insert(lfm, lm, jc, posn, incr);
+                j -= incr;
+            }
+            // these should be over the limit or illegal
+            check_insert(lfm, lm, jc, 0);
+            check_insert(lfm, lm, jc, 2, 2);
+            lfm.destroy_journal();
+        }
+    }
+
 private:
     static void load_vector(const u_int16_t a[], const size_t n, flist& v)
     {
@@ -164,7 +410,9 @@
     {
         lfmgr lm;
         BOOST_CHECK_EQUAL(lm.is_init(), false);
-        BOOST_CHECK_EQUAL(lm.size(), size_t(0));
+        BOOST_CHECK_EQUAL(lm.is_ae(), false);
+        BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), u_int16_t(0));
+        BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0));
         BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
@@ -177,15 +425,23 @@
 QPID_AUTO_TEST_CASE(initialize)
 {
     string test_name = get_test_name(test_filename, "initialize");
-    u_int16_t num_jfiles = 8;
+    const u_int16_t num_jfiles = 8;
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
+        {
+            lfmgr lm;
+            lfmgr_test_helper::initialize(lm, jc, num_jfiles, false, 0);
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::initialize(lm, jc, num_jfiles, true, 0);
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::initialize(lm, jc, num_jfiles, true, 5 * num_jfiles);
+        }
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
@@ -197,26 +453,30 @@
 QPID_AUTO_TEST_CASE(recover)
 {
     string test_name = get_test_name(test_filename, "recover");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
+        lid_fid_map lfm(test_name, test_name);
 
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+        {
+            lfmgr lm;
+            lfmgr_test_helper::prepare_recover(lfm, 8);
+            lfmgr_test_helper::recover(lfm, lm, jc, false, 0);
+            lfm.destroy_journal();
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::prepare_recover(lfm, 8);
+            lfmgr_test_helper::recover(lfm, lm, jc, true, 0);
+            lfm.destroy_journal();
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::prepare_recover(lfm, 8);
+            lfmgr_test_helper::recover(lfm, lm, jc, true, 5 * lfm.size());
+            lfm.destroy_journal();
+        }
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
@@ -228,24 +488,26 @@
 QPID_AUTO_TEST_CASE(initialize_finalize)
 {
     string test_name = get_test_name(test_filename, "initialize_finalize");
-    u_int16_t num_jfiles = 8;
+    const u_int16_t num_jfiles = 8;
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
-
-        lm.finalize();
-        BOOST_CHECK_EQUAL(lm.is_init(), false);
-        BOOST_CHECK_EQUAL(lm.size(), size_t(0));
-        BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
-        vector<u_int16_t> res;
-        lm.get_fid_list(res);
-        BOOST_CHECK_EQUAL(res.size(), size_t(0));
-        lm.get_lid_list(res);
-        BOOST_CHECK_EQUAL(res.size(), size_t(0));
+        {
+            lfmgr lm;
+            lfmgr_test_helper::initialize(lm, jc, num_jfiles, false, 0);
+            lfmgr_test_helper::finalize(lm);
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::initialize(lm, jc, num_jfiles, true, 0);
+            lfmgr_test_helper::finalize(lm);
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::initialize(lm, jc, num_jfiles, true, 5 * num_jfiles);
+            lfmgr_test_helper::finalize(lm);
+        }
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
@@ -257,517 +519,246 @@
 QPID_AUTO_TEST_CASE(recover_finalize)
 {
     string test_name = get_test_name(test_filename, "recover_finalize");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
+    const u_int16_t num_jfiles = 8;
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
+        lid_fid_map lfm(test_name, test_name);
 
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lm.finalize();
-        BOOST_CHECK_EQUAL(lm.is_init(), false);
-        BOOST_CHECK_EQUAL(lm.size(), size_t(0));
-        BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
-        vector<u_int16_t> res;
-        lm.get_fid_list(res);
-        BOOST_CHECK_EQUAL(res.size(), size_t(0));
-        lm.get_lid_list(res);
-        BOOST_CHECK_EQUAL(res.size(), size_t(0));
+        {
+            lfmgr lm;
+            lfmgr_test_helper::prepare_recover(lfm, num_jfiles);
+            lfmgr_test_helper::recover(lfm, lm, jc, false, 0);
+            lfmgr_test_helper::finalize(lm);
+            lfm.destroy_journal();
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::prepare_recover(lfm, num_jfiles);
+            lfmgr_test_helper::recover(lfm, lm, jc, true, 0);
+            lfmgr_test_helper::finalize(lm);
+            lfm.destroy_journal();
+        }
+        {
+            lfmgr lm;
+            lfmgr_test_helper::prepare_recover(lfm, num_jfiles);
+            lfmgr_test_helper::recover(lfm, lm, jc, true, 5 * lfm.size());
+            lfmgr_test_helper::finalize(lm);
+            lfm.destroy_journal();
+        }
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that initialize() correctly creates an ordered fid array _fcntl_arr after the lfmgr instance has been
-* initialized and finalized.
+* Check that 0 and/or null and other extreme/boundary parameters behave as expected.
 */
-QPID_AUTO_TEST_CASE(initialize_finalize_initialize)
+QPID_AUTO_TEST_CASE(zero_null_params)
 {
-    string test_name = get_test_name(test_filename, "initialize_finalize_initialize");
-    u_int16_t num_jfiles0 = 8;
-    u_int16_t num_jfiles1 = 12;
+    string test_name = get_test_name(test_filename, "zero_null_params");
+    const u_int16_t num_jfiles = 8;
     try
     {
         test_jrnl jc(test_name, test_dir, test_name);
+        lid_fid_map lfm(test_name, test_name);
         lfmgr lm;
+        lfmgr_test_helper::initialize(lfm, lm, jc, num_jfiles, true, 0);
 
-        lm.initialize(num_jfiles0, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles0);
-
-        lm.finalize();
-        BOOST_CHECK_EQUAL(lm.is_init(), false);
-
-        lm.initialize(num_jfiles1, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles1);
+        // Check that inserting 0 files works ok
+        lfmgr_test_helper::insert(lfm, lm, jc, 0, 0);
+        lfmgr_test_helper::insert(lfm, lm, jc, 2, 0);
+        lfmgr_test_helper::insert(lfm, lm, jc, num_jfiles - 1, 0);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that recover() correctly sets up the specified fid list order after the lfmgr instance has been initialized
-* and finalized.
+* Check that initialize()/recover() works correctly after a previous initialize()/recover() with/without an intervening
+* finalize().
 */
-QPID_AUTO_TEST_CASE(initialize_finalize_recover)
+QPID_AUTO_TEST_CASE(multiple_initialization_recover)
 {
-    string test_name = get_test_name(test_filename, "initialize_finalize_recover");
-    u_int16_t num_jfiles = 8;
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
-    try
-    {
-        test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
+    string test_name = get_test_name(test_filename, "multiple_initialization_recover");
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
 
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
-
-        lm.finalize();
-        BOOST_CHECK_EQUAL(lm.is_init(), false);
-
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.journal_insert(7);
-        lfm.journal_insert(8, 3);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-    }
-    catch(const exception& e) { BOOST_FAIL(e.what()); }
-    cout << "done" << endl;
-}
-
-/*
-* Check that initialize() correctly creates an ordered fid array _fcntl_arr after the lfmgr instance has been recovered
-* and finalized.
-*/
-QPID_AUTO_TEST_CASE(recover_finalize_initialize)
-{
-    string test_name = get_test_name(test_filename, "recover_finalize_initialize");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
-    u_int16_t num_jfiles = 12;
+    // Set combinations of value pairs to be used for number of journal files in first and second init
+    u_int16_t num_jfiles_arr[][2] = {{8, 12}, {4, 7}, {0, 0}}; // end with zeros
     try
     {
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lm.finalize();
-        BOOST_CHECK_EQUAL(lm.is_init(), false);
-
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
+        lid_fid_map lfm(test_name, test_name);
+        for (unsigned p = 0; p < 8; p++)
+        {
+            const bool i_0 = p & 0x01; // first bit
+            const bool i_1 = p & 0x02; // second bit
+            const bool f = p & 0x04;   // third bit
+            lfmgr_test_helper::check_multiple_initialization_recover(lfm, jc, num_jfiles_arr, i_0,f, i_1);
+        }
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that recover() correctly sets up the specified fid list order after the lfmgr instance has been recovered and
-* finalized.
+* Check that insert() works correctly after initialize() and shifts the fid sequence beyond the insert point correctly:
+*
+* The following sequence is tested:
+* initialize 4           fids=[0,1,2,3]           lids=[0,1,2,3]
+* insert 1 after lid 0   fids=[0,4,1,2,3]         lids=[0,2,3,4,1]
+* insert 2 after lid 2   fids=[0,4,1,5,6,2,3]     lids=[0,2,5,6,1,3,4]
+* insert 1 after lid 6   fids=[0,4,1,5,6,2,3,7]   lids=[0,2,5,6,1,3,4,7]
+* issert 1 after lid 3   fids=[0,4,1,5,8,6,2,3,7] lids=[0,2,6,7,1,3,5,8,4]
 */
-QPID_AUTO_TEST_CASE(recover_finalize_recover)
+QPID_AUTO_TEST_CASE(initialize_insert)
 {
-    string test_name = get_test_name(test_filename, "recover_finalize_recover");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
+    string test_name = get_test_name(test_filename, "initialize_insert");
+    const u_int16_t initial_num_jfiles = 8;
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
+        lid_fid_map lfm(test_name, test_name);
         lfmgr lm;
+        lfmgr_test_helper::initialize(lfm, lm, jc, initial_num_jfiles, true, 0);
 
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lm.finalize();
-        BOOST_CHECK_EQUAL(lm.is_init(), false);
-
-        lfm.journal_insert(3);
-        lfm.journal_insert(8, 3);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+        lfmgr_test_helper::insert(lfm, lm, jc, 0);
+        lfmgr_test_helper::insert(lfm, lm, jc, 2, 2);
+        lfmgr_test_helper::insert(lfm, lm, jc, 6);
+        lfmgr_test_helper::insert(lfm, lm, jc, 3);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that a second call to initialize() without calling finilize() correctly clears the first initialize and
-* correctly creates an ordered fid array of the correct size _fcntl_arr.
+* Check that insert() works correctly after recover() and shifts the fid sequence beyond the insert point correctly:
+*
+* The following sequence is tested:
+* recover 4              fids=[0,2,3,1]           lids=[0,3,1,2]
+* insert 1 after lid 0   fids=[0,4,2,3,1]         lids=[0,4,2,3,1]
+* insert 2 after lid 2   fids=[0,4,2,5,6,3,1]     lids=[0,6,2,5,1,3,4]
+* insert 1 after lid 6   fids=[0,4,2,5,6,3,1,7]   lids=[0,6,2,5,1,3,4,7]
+* issert 1 after lid 3   fids=[0,4,2,5,8,6,3,1,7] lids=[0,7,2,6,1,3,5,8,4]
 */
-QPID_AUTO_TEST_CASE(initialize_initialize)
+QPID_AUTO_TEST_CASE(recover_insert)
 {
-    string test_name = get_test_name(test_filename, "initialize_initialize");
-    u_int16_t num_jfiles0 = 8;
-    u_int16_t num_jfiles1 = 12;
+    string test_name = get_test_name(test_filename, "recover_insert");
+    const u_int16_t initial_num_jfiles = 4;
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
+        lid_fid_map lfm(test_name, test_name);
         lfmgr lm;
+        lfmgr_test_helper::prepare_recover(lfm, initial_num_jfiles);
+        lfmgr_test_helper::recover(lfm, lm, jc, true, 0);
 
-        lm.initialize(num_jfiles0, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles0);
-
-        lm.initialize(num_jfiles1, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles1);
+        lfmgr_test_helper::insert(lfm, lm, jc, 0);
+        lfmgr_test_helper::insert(lfm, lm, jc, 2, 2);
+        lfmgr_test_helper::insert(lfm, lm, jc, 6);
+        lfmgr_test_helper::insert(lfm, lm, jc, 3);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that a call to recover() after initialize() without calling finilize() correctly clears the first initialize and
-* correctly sets up the specified fid list order.
+* Check that illegal ae parameter combinations are caught and result in an exception being thrown.
 */
-QPID_AUTO_TEST_CASE(initialize_recover)
+QPID_AUTO_TEST_CASE(ae_parameters)
 {
-    string test_name = get_test_name(test_filename, "initialize_recover");
-    u_int16_t num_jfiles = 8;
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
+    string test_name = get_test_name(test_filename, "ae_parameters");
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
+        lid_fid_map lfm(test_name, test_name);
+        const u_int16_t num_jfiles = 8;
         lfmgr lm;
+        
+        for (unsigned i = 0; i < 2; i++)
+        {
+            if (i)
+                lfmgr_test_helper::initialize(lfm, lm, jc, num_jfiles, false, 0);
+            else
+            {
+                lfmgr_test_helper::prepare_recover(lfm, num_jfiles);
+                lfmgr_test_helper::recover(lfm, lm, jc, false, 0);
+            }
 
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
-
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.journal_insert(7);
-        lfm.journal_insert(8, 3);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+            lfmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, num_jfiles - 2);
+            lfmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, 0);
+            lfmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, 2 * num_jfiles);
+            lfmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, num_jfiles);
+            lfm.destroy_journal();
+        }
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that a call to initialize() after recover() without calling finilize() correctly clears the first recover and
-* correctly creates an ordered fid array of the correct size _fcntl_arr.
+* Check that initialized or recovered journals with auto-expand disabled will not allow either inserts or appends.
 */
-QPID_AUTO_TEST_CASE(recover_initialize)
+QPID_AUTO_TEST_CASE(ae_disabled)
 {
-    string test_name = get_test_name(test_filename, "recover_initialize");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
-    u_int16_t num_jfiles = 12;
+    string test_name = get_test_name(test_filename, "ae_disabled");
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
+        lid_fid_map lfm(test_name, test_name);
+        lfmgr_test_helper::check_limit(lfm, jc, false, 8, 0);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that a second call to recover() without calling finilize() correctly clears the first recover and correctly
-* sets up the specified fid list order.
+* Check that initialized or recovered journals with auto-expand enabled and a file limit set will enforce the correct
+* limits on inserts and appends.
 */
-QPID_AUTO_TEST_CASE(recover_recover)
+QPID_AUTO_TEST_CASE(ae_enabled_limit)
 {
-    string test_name = get_test_name(test_filename, "recover_recover");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
+    string test_name = get_test_name(test_filename, "ae_enabled_limit");
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lfm.journal_insert(3);
-        lfm.journal_insert(8, 3);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        BOOST_CHECK_EQUAL(lm.is_init(), true);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+        lid_fid_map lfm(test_name, test_name);
+        lfmgr_test_helper::check_limit(lfm, jc, true, 8, 32);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that append correctly adds to the end of the array _fcntl_arr after initialize().
+* Check that initialized or recovered journals with auto-expand enabled and no file limit set (0) will allow inserts and
+* appends up to the file limit JRNL_MAX_NUM_FILES.
 */
-QPID_AUTO_TEST_CASE(initialize_append)
+QPID_AUTO_TEST_CASE(ae_enabled_unlimited)
 {
-    string test_name = get_test_name(test_filename, "initialize_append");
-    u_int16_t num_jfiles = 8;
-    u_int16_t num_append_jfiles = 3;
+    string test_name = get_test_name(test_filename, "ae_enabled_unlimited");
+    ::srand48(1); // init random gen for repeatable tests when using lfmgr_test_helper::prepare_recover()
     try
     {
+        jdir::create_dir(test_dir); // Check test dir exists; create it if not
         test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
-
-        // Append single file
-        lm.append(&jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles + 1);
-
-        // Append 3 more files
-        lm.append(&jc, &jc.new_fcntl, num_append_jfiles);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles + 1 + num_append_jfiles);
+        lid_fid_map lfm(test_name, test_name);
+        lfmgr_test_helper::check_limit(lfm, jc, true, 8, 0);
     }
     catch(const exception& e) { BOOST_FAIL(e.what()); }
     cout << "done" << endl;
 }
 
 /*
-* Check that append correctly adds to the end of the array _fcntl_arr after recover().
-*/
-QPID_AUTO_TEST_CASE(recover_append)
-{
-    string test_name = get_test_name(test_filename, "recover_append");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
-    try
-    {
-        test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-
-        lfm.journal_create(4, 4);
-        lfm.journal_insert(0);
-        lfm.journal_insert(2, 2);
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        // Append single file
-        lfm.journal_insert(7);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lm.append(&jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        // Append 3 more files
-        lfm.journal_insert(8, 3);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lm.append(&jc, &jc.new_fcntl, 3);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-    }
-    catch(const exception& e) { BOOST_FAIL(e.what()); }
-    cout << "done" << endl;
-}
-
-/*
-* Check that insert() works correctly after initialize() and shifts the fid sequence beyond the insert point correctly:
-*
-* The following sequence is tested:
-* initialize 4           fids=[0,1,2,3]           lids=[0,1,2,3]
-* insert 1 after lid 0   fids=[0,4,1,2,3]         lids=[0,2,3,4,1]
-* insert 2 after lid 2   fids=[0,4,1,5,6,2,3]     lids=[0,2,5,6,1,3,4]
-* insert 1 after lid 6   fids=[0,4,1,5,6,2,3,7]   lids=[0,2,5,6,1,3,4,7]
-* issert 1 after lid 3   fids=[0,4,1,5,8,6,2,3,7] lids=[0,2,6,7,1,3,5,8,4]
-*/
-QPID_AUTO_TEST_CASE(initialize_insert)
-{
-    string test_name = get_test_name(test_filename, "initialize_insert");
-    u_int16_t num_jfiles = 4;
-    u_int16_t fids1[] = {0, 4, 1, 2, 3};
-    u_int16_t lids1[] = {0, 2, 3, 4, 1};
-    u_int16_t fids2[] = {0, 4, 1, 5, 6, 2, 3};
-    u_int16_t lids2[] = {0, 2, 5, 6, 1, 3, 4};
-    u_int16_t fids3[] = {0, 4, 1, 5, 6, 2, 3, 7};
-    u_int16_t lids3[] = {0, 2, 5, 6, 1, 3, 4, 7};
-    u_int16_t fids4[] = {0, 4, 1, 5, 8, 6, 2, 3, 7};
-    u_int16_t lids4[] = {0, 2, 6, 7, 1, 3, 5, 8, 4};
-    try
-    {
-        test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-        lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
-
-        lm.insert(0, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fids1, lids1, num_jfiles + 1);
-
-        lm.insert(2, &jc, &jc.new_fcntl, 2);
-        lfmgr_test_helper::check_fids_lids(lm, fids2, lids2, num_jfiles + 3);
-
-        lm.insert(6, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fids3, lids3, num_jfiles + 4);
-
-        lm.insert(3, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fids4, lids4, num_jfiles + 5);
-    }
-    catch(const exception& e) { BOOST_FAIL(e.what()); }
-    cout << "done" << endl;
-}
-
-/*
-* Check that insert() works correctly after recover() and shifts the fid sequence beyond the insert point correctly:
-*
-* The following sequence is tested:
-* recover 4              fids=[0,2,3,1]           lids=[0,3,1,2]
-* insert 1 after lid 0   fids=[0,4,2,3,1]         lids=[0,4,2,3,1]
-* insert 2 after lid 2   fids=[0,4,2,5,6,3,1]     lids=[0,6,2,5,1,3,4]
-* insert 1 after lid 6   fids=[0,4,2,5,6,3,1,7]   lids=[0,6,2,5,1,3,4,7]
-* issert 1 after lid 3   fids=[0,4,2,5,8,6,3,1,7] lids=[0,7,2,6,1,3,5,8,4]
-*/
-QPID_AUTO_TEST_CASE(recover_insert)
-{
-    string test_name = get_test_name(test_filename, "recover_insert");
-    lid_fid_map lfm(test_name, test_name);
-    flist fidl;
-    flist lidl;
-    rcvdat rd;
-    try
-    {
-        lfm.journal_create(4, 4);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lfm.write_journal();
-        lfmgr_test_helper::rcvdat_init(rd, fidl);
-        test_jrnl jc(test_name, test_dir, test_name);
-        lfmgr lm;
-        lm.recover(rd, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lfm.journal_insert(0);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lm.insert(0, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lfm.journal_insert(2, 2);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lm.insert(2, &jc, &jc.new_fcntl, 2);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lfm.journal_insert(6);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lm.insert(6, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-
-        lfm.journal_insert(3);
-        lfm.get_fid_list(fidl);
-        lfm.get_lid_list(lidl);
-        lm.insert(3, &jc, &jc.new_fcntl);
-        lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
-    }
-    catch(const exception& e) { BOOST_FAIL(e.what()); }
-    cout << "done" << endl;
-}
-
-/*
 * Tests randomized combinations of initialization/recovery, initial size, number, size and location of inserts.
 *
 * To reproduce a specific test, comment out the get_seed() statement and uncomment the literal below, adjusting the seed
@@ -777,7 +768,7 @@
 {
     string test_name = get_test_name(test_filename, "randomized_tests");
     const long seed = get_seed();
-    // const long seed = 0xd94c29b3;
+    // const long seed = 0x2d9b69d32;
     cout << "seed=0x" << hex << seed << dec << " " << flush;
     ::srand48(seed);
 
@@ -785,20 +776,24 @@
     flist fidl;
     flist lidl;
     rcvdat rd;
+    u_int16_t curr_ae_max_jfiles = 0;
+    jdir::create_dir(test_dir); // Check test dir exists; create it if not
     
     for (int test_num = 0; test_num < 100; test_num++)
     {
         test_jrnl jc(test_name, test_dir, test_name);
         lfmgr lm;
-        // 50% chance of recovery except first run and if >= 800 journal files
-        const bool recover_flag = test_num > 0 && lfm.size() < 800 ? 2.0 * ::drand48() < 1.0 : false;
+        // 50% chance of recovery except first run and if there is still ae space left
+        const bool recover_flag = test_num > 0 &&
+                                  curr_ae_max_jfiles > lfm.size() &&
+                                  2.0 * ::drand48() < 1.0;
         if (recover_flag)
         {
             // Recover from previous iteration
             lfm.get_fid_list(fidl);
             lfm.get_lid_list(lidl);
-            lfm.write_journal();
-            lfmgr_test_helper::rcvdat_init(rd, fidl);
+            lfm.write_journal(true, curr_ae_max_jfiles);
+            lfmgr_test_helper::rcvdat_init(rd, fidl, true, curr_ae_max_jfiles);
             lm.recover(rd, &jc, &jc.new_fcntl);
             lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
         }
@@ -806,31 +801,53 @@
         {
             // Initialize from scratch
             const u_int16_t num_jfiles = 4 + u_int16_t(21.0 * ::drand48()); // size: 4 - 25 files
+            curr_ae_max_jfiles = u_int16_t(4 * num_jfiles * ::drand48()); // size: 0 - 100 files
+            if (curr_ae_max_jfiles > JRNL_MAX_NUM_FILES) curr_ae_max_jfiles = JRNL_MAX_NUM_FILES;
+            else if (curr_ae_max_jfiles <= num_jfiles) curr_ae_max_jfiles = 0;
             lfm.destroy_journal();
             lfm.journal_create(num_jfiles, num_jfiles);
             lfm.get_fid_list(fidl);
             lfm.get_lid_list(lidl);
-            lm.initialize(num_jfiles, &jc, &jc.new_fcntl);
+            lm.initialize(num_jfiles, true, curr_ae_max_jfiles, &jc, &jc.new_fcntl);
             lfmgr_test_helper::check_linear_fids_lids(lm, num_jfiles);
         }
 
         // Loop to insert fids
-        const int num_inserts = 1 + int(lfm.size()/10.0 * ::drand48());
+        const int num_inserts = 1 + int(lfm.size() * ::drand48());
         for (int i = 0; i < num_inserts; i++)
         {
-            const u_int16_t size = lm.size();
+            const u_int16_t size = lm.num_jfiles();
             const u_int16_t after_lid = u_int16_t(1.0 * size * ::drand48());
-            const u_int16_t num_files = 1 + u_int16_t(4.0 * ::drand48());
-            lfm.journal_insert(after_lid, num_files);
-            lfm.get_fid_list(fidl);
-            lfm.get_lid_list(lidl);
+            const u_int16_t num_jfiles = 1 + u_int16_t(4.0 * ::drand48());
+            const bool legal = lm.ae_max_jfiles()
+                               ? size + num_jfiles <= lm.ae_max_jfiles()
+                               : size + num_jfiles <= JRNL_MAX_NUM_FILES;
+            if (legal)
+            {
+                lfm.journal_insert(after_lid, num_jfiles);
+                lfm.get_fid_list(fidl);
+                lfm.get_lid_list(lidl);
 
-            lm.insert(after_lid, &jc, &jc.new_fcntl, num_files);
-            lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+                lm.insert(after_lid, &jc, &jc.new_fcntl, num_jfiles);
+                lfmgr_test_helper::check_fids_lids(lm, fidl, lidl);
+            }
+            else
+            {
+                try
+                {
+                    lm.insert(after_lid, &jc, &jc.new_fcntl, num_jfiles);
+                    BOOST_FAIL("lfmgr::insert() succeeded and exceeded limit");
+                }
+                catch (const jexception& e)
+                {
+                    BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEFNUMLIMIT);
+                    break; // no more inserts...
+                }
+            }
         }
         lm.finalize();
         BOOST_CHECK_EQUAL(lm.is_init(), false);
-        BOOST_CHECK_EQUAL(lm.size(), size_t(0));
+        BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0));
         BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0);
     }
     cout << "done" << endl;




More information about the rhmessaging-commits mailing list