Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

rep_region.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2001-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: rep_region.c,v 12.12 2005/10/19 19:10:40 sue Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #if TIME_WITH_SYS_TIME
00014 #include <sys/time.h>
00015 #include <time.h>
00016 #else
00017 #if HAVE_SYS_TIME_H
00018 #include <sys/time.h>
00019 #else
00020 #include <time.h>
00021 #endif
00022 #endif
00023 
00024 #include <string.h>
00025 #endif
00026 
00027 #include "db_int.h"
00028 #include "dbinc/db_page.h"
00029 #include "dbinc/db_am.h"
00030 #include "dbinc/log.h"
00031 
00032 static int __rep_egen_init  __P((DB_ENV *, REP *));
00033 
00034 /*
00035  * __rep_region_init --
00036  *      Initialize the shared memory state for the replication system.
00037  *
00038  * PUBLIC: int __rep_region_init __P((DB_ENV *));
00039  */
00040 int
00041 __rep_region_init(dbenv)
00042         DB_ENV *dbenv;
00043 {
00044         REGENV *renv;
00045         REGINFO *infop;
00046         DB_REP *db_rep;
00047         REP *rep;
00048         int ret;
00049 
00050         db_rep = dbenv->rep_handle;
00051         infop = dbenv->reginfo;
00052         renv = infop->primary;
00053         ret = 0;
00054 
00055         if (renv->rep_off == INVALID_ROFF) {
00056                 /* Must create the region. */
00057                 if ((ret = __db_shalloc(infop, sizeof(REP), 0, &rep)) != 0)
00058                         return (ret);
00059                 memset(rep, 0, sizeof(*rep));
00060                 rep->tally_off = INVALID_ROFF;
00061                 rep->v2tally_off = INVALID_ROFF;
00062                 renv->rep_off = R_OFFSET(infop, rep);
00063 
00064                 if ((ret = __mutex_alloc(
00065                     dbenv, MTX_REP_REGION, 0, &rep->mtx_region)) != 0)
00066                         return (ret);
00067 
00068                 /*
00069                  * Because we have no way to prevent deadlocks and cannot log
00070                  * changes made to it, we single-thread access to the client
00071                  * bookkeeping database.  This is suboptimal, but it only gets
00072                  * accessed when messages arrive out-of-order, so it should
00073                  * stay small and not be used in a high-performance app.
00074                  */
00075                 if ((ret = __mutex_alloc(
00076                     dbenv, MTX_REP_DATABASE, 0, &rep->mtx_clientdb)) != 0)
00077                         return (ret);
00078 
00079                 /* We have the region; fill in the values. */
00080                 rep->eid = DB_EID_INVALID;
00081                 rep->master_id = DB_EID_INVALID;
00082                 rep->gen = 0;
00083                 if ((ret = __rep_egen_init(dbenv, rep)) != 0)
00084                         return (ret);
00085                 /*
00086                  * Set default values for the min and max log records that we
00087                  * wait before requesting a missing log record.
00088                  */
00089                 rep->request_gap = DB_REP_REQUEST_GAP;
00090                 rep->max_gap = DB_REP_MAX_GAP;
00091                 F_SET(rep, REP_F_NOARCHIVE);
00092                 (void)time(&renv->rep_timestamp);
00093                 renv->op_timestamp = 0;
00094                 F_CLR(renv, DB_REGENV_REPLOCKED);
00095         } else
00096                 rep = R_ADDR(infop, renv->rep_off);
00097 
00098         db_rep->region = rep;
00099 
00100         return (0);
00101 }
00102 
00103 /*
00104  * __rep_region_destroy --
00105  *      Destroy any system resources allocated in the replication region.
00106  *
00107  * PUBLIC: int __rep_region_destroy __P((DB_ENV *));
00108  */
00109 int
00110 __rep_region_destroy(dbenv)
00111         DB_ENV *dbenv;
00112 {
00113         DB_REP *db_rep;
00114         REGENV *renv;
00115         REGINFO *infop;
00116         int ret, t_ret;
00117 
00118         if (!REP_ON(dbenv))
00119                 return (0);
00120 
00121         ret = 0;
00122 
00123         db_rep = dbenv->rep_handle;
00124         if (db_rep->region != NULL) {
00125                 ret = __mutex_free(dbenv, &db_rep->region->mtx_region);
00126                 if ((t_ret = __mutex_free(
00127                     dbenv, &db_rep->region->mtx_clientdb)) != 0 && ret == 0)
00128                         ret = t_ret;
00129         }
00130 
00131         infop = dbenv->reginfo;
00132         renv = infop->primary;
00133         if (renv->rep_off != INVALID_ROFF)
00134                 __db_shalloc_free(infop, R_ADDR(infop, renv->rep_off));
00135 
00136         return (ret);
00137 }
00138 
00139 /*
00140  * __rep_dbenv_refresh --
00141  *      Replication-specific refresh of the DB_ENV structure.
00142  *
00143  * PUBLIC: void __rep_dbenv_refresh __P((DB_ENV *));
00144  */
00145 void
00146 __rep_dbenv_refresh(dbenv)
00147         DB_ENV *dbenv;
00148 {
00149         if (REP_ON(dbenv))
00150                 ((DB_REP *)dbenv->rep_handle)->region = NULL;
00151         return;
00152 }
00153 
00154 /*
00155  * __rep_dbenv_close --
00156  *      Replication-specific destruction of the DB_ENV structure.
00157  *
00158  * PUBLIC: int __rep_dbenv_close __P((DB_ENV *));
00159  */
00160 int
00161 __rep_dbenv_close(dbenv)
00162         DB_ENV *dbenv;
00163 {
00164         if (REP_ON(dbenv)) {
00165                 __os_free(dbenv, dbenv->rep_handle);
00166                 dbenv->rep_handle = NULL;
00167                 dbenv->rep_send = NULL;
00168         }
00169 
00170         return (0);
00171 }
00172 
00173 /*
00174  * __rep_preclose --
00175  *      If we are a client, shut down our client database and close
00176  * all databases we've opened while applying messages as a client.
00177  *
00178  * PUBLIC: int __rep_preclose __P((DB_ENV *));
00179  */
00180 int
00181 __rep_preclose(dbenv)
00182         DB_ENV *dbenv;
00183 {
00184         DB_LOG *dblp;
00185         DB_REP *db_rep;
00186         LOG *lp;
00187         REP_BULK bulk;
00188         int ret, t_ret;
00189 
00190         ret = 0;
00191 
00192         db_rep = dbenv->rep_handle;
00193         dblp = dbenv->lg_handle;
00194         lp = dblp->reginfo.primary;
00195 
00196         MUTEX_LOCK(dbenv, db_rep->region->mtx_clientdb);
00197         if (db_rep->rep_db != NULL) {
00198                 ret = __db_close(db_rep->rep_db, NULL, DB_NOSYNC);
00199                 db_rep->rep_db = NULL;
00200         }
00201 
00202         if ((t_ret = __dbreg_close_files(dbenv)) != 0 && ret == 0)
00203                 ret = t_ret;
00204         F_CLR(db_rep, DBREP_OPENFILES);
00205         /*
00206          * If we have something in the bulk buffer, send anything in it
00207          * if we are able to.
00208          */
00209         if (lp->bulk_off != 0 && dbenv->rep_send != NULL) {
00210                 memset(&bulk, 0, sizeof(bulk));
00211                 bulk.addr = R_ADDR(&dblp->reginfo, lp->bulk_buf);
00212                 bulk.offp = &lp->bulk_off;
00213                 bulk.len = lp->bulk_len;
00214                 bulk.type = REP_BULK_LOG;
00215                 bulk.eid = DB_EID_BROADCAST;
00216                 bulk.flagsp = &lp->bulk_flags;
00217                 if ((t_ret = __rep_send_bulk(dbenv, &bulk, 0)) != 0 && ret == 0)
00218                         ret = t_ret;
00219         }
00220         MUTEX_UNLOCK(dbenv, db_rep->region->mtx_clientdb);
00221         return (ret);
00222 }
00223 
00224 /*
00225  * __rep_egen_init --
00226  *      Initialize the value of egen in the region.  Called only from
00227  *      __rep_region_init, which is guaranteed to be single-threaded
00228  *      as we create the rep region.  We set the rep->egen field which
00229  *      is normally protected by db_rep->region->mutex.
00230  */
00231 static int
00232 __rep_egen_init(dbenv, rep)
00233         DB_ENV *dbenv;
00234         REP *rep;
00235 {
00236         DB_FH *fhp;
00237         int ret;
00238         size_t cnt;
00239         char *p;
00240 #ifdef DIAGNOSTIC
00241         DB_MSGBUF mb;
00242 #endif
00243 
00244         if ((ret =
00245             __db_appname(dbenv, DB_APP_NONE, REP_EGENNAME, 0, NULL, &p)) != 0)
00246                 return (ret);
00247         /*
00248          * If the file doesn't exist, create it now and initialize with 1.
00249          */
00250         if (__os_exists(p, NULL) != 0) {
00251                 rep->egen = rep->gen + 1;
00252                 if ((ret = __rep_write_egen(dbenv, rep->egen)) != 0)
00253                         goto err;
00254         } else {
00255                 /*
00256                  * File exists, open it and read in our egen.
00257                  */
00258                 if ((ret = __os_open(dbenv, p, DB_OSO_RDONLY,
00259                     __db_omode(OWNER_RW), &fhp)) != 0)
00260                         goto err;
00261                 if ((ret = __os_read(dbenv, fhp, &rep->egen, sizeof(u_int32_t),
00262                     &cnt)) < 0 || cnt == 0)
00263                         goto err1;
00264                 RPRINT(dbenv, rep, (dbenv, &mb, "Read in egen %lu",
00265                     (u_long)rep->egen));
00266 err1:            (void)__os_closehandle(dbenv, fhp);
00267         }
00268 err:    __os_free(dbenv, p);
00269         return (ret);
00270 }
00271 
00272 /*
00273  * __rep_write_egen --
00274  *      Write out the egen into the env file.
00275  *
00276  * PUBLIC: int __rep_write_egen __P((DB_ENV *, u_int32_t));
00277  */
00278 int
00279 __rep_write_egen(dbenv, egen)
00280         DB_ENV *dbenv;
00281         u_int32_t egen;
00282 {
00283         DB_FH *fhp;
00284         int ret;
00285         size_t cnt;
00286         char *p;
00287 
00288         if ((ret =
00289             __db_appname(dbenv, DB_APP_NONE, REP_EGENNAME, 0, NULL, &p)) != 0)
00290                 return (ret);
00291         if ((ret = __os_open(dbenv, p, DB_OSO_CREATE | DB_OSO_TRUNC,
00292             __db_omode(OWNER_RW), &fhp)) == 0) {
00293                 if ((ret = __os_write(dbenv, fhp, &egen, sizeof(u_int32_t),
00294                     &cnt)) != 0 || ((ret = __os_fsync(dbenv, fhp)) != 0))
00295                         __db_err(dbenv, "%s: %s", p, db_strerror(ret));
00296                 (void)__os_closehandle(dbenv, fhp);
00297         }
00298         __os_free(dbenv, p);
00299         return (ret);
00300 }

Generated on Sun Dec 25 12:14:45 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2