diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-02-17 17:25:57 +0000 |
|---|---|---|
| committer | <> | 2015-03-17 16:26:24 +0000 |
| commit | 780b92ada9afcf1d58085a83a0b9e6bc982203d1 (patch) | |
| tree | 598f8b9fa431b228d29897e798de4ac0c1d3d970 /src/dbreg | |
| parent | 7a2660ba9cc2dc03a69ddfcfd95369395cc87444 (diff) | |
| download | berkeleydb-master.tar.gz | |
Diffstat (limited to 'src/dbreg')
| -rw-r--r-- | src/dbreg/dbreg.c | 18 | ||||
| -rw-r--r-- | src/dbreg/dbreg.src | 27 | ||||
| -rw-r--r-- | src/dbreg/dbreg_auto.c | 12 | ||||
| -rw-r--r-- | src/dbreg/dbreg_autop.c | 17 | ||||
| -rw-r--r-- | src/dbreg/dbreg_rec.c | 154 | ||||
| -rw-r--r-- | src/dbreg/dbreg_stat.c | 2 | ||||
| -rw-r--r-- | src/dbreg/dbreg_util.c | 73 |
7 files changed, 270 insertions, 33 deletions
diff --git a/src/dbreg/dbreg.c b/src/dbreg/dbreg.c index 5067edac..99a80959 100644 --- a/src/dbreg/dbreg.c +++ b/src/dbreg/dbreg.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -9,6 +9,7 @@ #include "db_config.h" #include "db_int.h" +#include "dbinc/blob.h" #include "dbinc/db_page.h" #include "dbinc/log.h" #include "dbinc/txn.h" @@ -171,6 +172,7 @@ __dbreg_setup(dbp, fname, dname, create_txnid) F_SET(fnp, DBREG_EXCL); fnp->txn_ref = 1; fnp->mutex = dbp->mutex; + fnp->blob_file_id = dbp->blob_file_id; dbp->log_filename = fnp; @@ -722,7 +724,7 @@ __dbreg_failchk(env) MUTEX_LOCK(env, lp->mtx_filelist); for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname); fnp != NULL; fnp = nnp) { nnp = SH_TAILQ_NEXT(fnp, q, __fname); - if (dbenv->is_alive(dbenv, + if (dbenv->is_alive(dbenv, fnp->pid, unused, DB_MUTEX_PROCESS_ONLY)) continue; MUTEX_LOCK(env, fnp->mutex); @@ -773,6 +775,7 @@ __dbreg_log_close(env, fnp, txn, op) DB_LOG *dblp; DB_LSN r_unused; int ret; + u_int32_t blob_file_lo, blob_file_hi; dblp = env->lg_handle; ret = 0; @@ -788,10 +791,12 @@ __dbreg_log_close(env, fnp, txn, op) memset(&fid_dbt, 0, sizeof(fid_dbt)); fid_dbt.data = fnp->ufid; fid_dbt.size = DB_FILE_ID_LEN; + SET_LO_HI_VAR(fnp->blob_file_id, blob_file_lo, blob_file_hi); if ((ret = __dbreg_register_log(env, txn, &r_unused, F_ISSET(fnp, DB_FNAME_DURABLE) ? 0 : DB_LOG_NOT_DURABLE, op, dbtp, &fid_dbt, fnp->id, - fnp->s_type, fnp->meta_pgno, TXN_INVALID)) != 0) { + fnp->s_type, fnp->meta_pgno, TXN_INVALID, blob_file_lo, + blob_file_hi)) != 0) { /* * We are trying to close, but the log write failed. * Unfortunately, close needs to plow forward, because @@ -958,6 +963,7 @@ __dbreg_log_id(dbp, txn, id, needlock) LOG *lp; u_int32_t op; int i, ret; + u_int32_t blob_file_lo, blob_file_hi; env = dbp->env; dblp = env->lg_handle; @@ -996,14 +1002,16 @@ __dbreg_log_id(dbp, txn, id, needlock) fid_dbt.size = DB_FILE_ID_LEN; op = !F_ISSET(dbp, DB_AM_OPEN_CALLED) ? DBREG_PREOPEN : - (F_ISSET(dbp, DB_AM_INMEM) ? + (F_ISSET(dbp, DB_AM_INMEM) ? (F2_ISSET(dbp, DB2_AM_EXCL) ? DBREG_XREOPEN : DBREG_REOPEN): (F2_ISSET(dbp, DB2_AM_EXCL) ? DBREG_XOPEN : DBREG_OPEN)); + SET_LO_HI_VAR(fnp->blob_file_id, blob_file_lo, blob_file_hi); ret = __dbreg_register_log(env, txn, &unused, F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0, op | F_ISSET(fnp, DB_FNAME_DBREG_MASK), r_name.size == 0 ? NULL : &r_name, &fid_dbt, id, - fnp->s_type, fnp->meta_pgno, fnp->create_txnid); + fnp->s_type, fnp->meta_pgno, fnp->create_txnid, + blob_file_lo, blob_file_hi); if (needlock) MUTEX_UNLOCK(env, lp->mtx_filelist); diff --git a/src/dbreg/dbreg.src b/src/dbreg/dbreg.src index c7740d63..3187bc4f 100644 --- a/src/dbreg/dbreg.src +++ b/src/dbreg/dbreg.src @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -26,7 +26,7 @@ INCLUDE * ftype: database type * id: transaction id of the subtransaction that created the fs object */ -BEGIN register 42 2 +BEGIN_COMPAT register 42 2 DBOP opcode u_int32_t lu DBT name DBT s DBT uid DBT s @@ -35,3 +35,26 @@ ARG ftype DBTYPE lx ARG meta_pgno db_pgno_t lu ARG id u_int32_t lx END + +/* + * Used for registering name/id translations at open or close. + * opcode: register or unregister + * name: file name + * fileid: unique file id + * ftype: file type + * ftype: database type + * id: transaction id of the subtransaction that created the fs object + * blob_fid_lo/hi: The blob file directory id + */ +BEGIN register 61 2 +DBOP opcode u_int32_t lu +DBT name DBT s +DBT uid DBT s +ARG fileid int32_t ld +ARG ftype DBTYPE lx +ARG meta_pgno db_pgno_t lu +ARG id u_int32_t lx +ARG blob_fid_lo u_int32_t lu +ARG blob_fid_hi u_int32_t lu +END + diff --git a/src/dbreg/dbreg_auto.c b/src/dbreg/dbreg_auto.c index a26e5527..3d9f01c7 100644 --- a/src/dbreg/dbreg_auto.c +++ b/src/dbreg/dbreg_auto.c @@ -8,6 +8,16 @@ #include "dbinc/db_am.h" #include "dbinc/txn.h" +DB_LOG_RECSPEC __dbreg_register_42_desc[] = { + {LOGREC_DBOP, SSZ(__dbreg_register_42_args, opcode), "opcode", ""}, + {LOGREC_DBT, SSZ(__dbreg_register_42_args, name), "name", ""}, + {LOGREC_DBT, SSZ(__dbreg_register_42_args, uid), "uid", ""}, + {LOGREC_ARG, SSZ(__dbreg_register_42_args, fileid), "fileid", "%ld"}, + {LOGREC_ARG, SSZ(__dbreg_register_42_args, ftype), "ftype", "%lx"}, + {LOGREC_ARG, SSZ(__dbreg_register_42_args, meta_pgno), "meta_pgno", "%lu"}, + {LOGREC_ARG, SSZ(__dbreg_register_42_args, id), "id", "%lx"}, + {LOGREC_Done, 0, "", ""} +}; DB_LOG_RECSPEC __dbreg_register_desc[] = { {LOGREC_DBOP, SSZ(__dbreg_register_args, opcode), "opcode", ""}, {LOGREC_DBT, SSZ(__dbreg_register_args, name), "name", ""}, @@ -16,6 +26,8 @@ DB_LOG_RECSPEC __dbreg_register_desc[] = { {LOGREC_ARG, SSZ(__dbreg_register_args, ftype), "ftype", "%lx"}, {LOGREC_ARG, SSZ(__dbreg_register_args, meta_pgno), "meta_pgno", "%lu"}, {LOGREC_ARG, SSZ(__dbreg_register_args, id), "id", "%lx"}, + {LOGREC_ARG, SSZ(__dbreg_register_args, blob_fid_lo), "blob_fid_lo", "%lu"}, + {LOGREC_ARG, SSZ(__dbreg_register_args, blob_fid_hi), "blob_fid_hi", "%lu"}, {LOGREC_Done, 0, "", ""} }; /* diff --git a/src/dbreg/dbreg_autop.c b/src/dbreg/dbreg_autop.c index ea43addd..931bc2d9 100644 --- a/src/dbreg/dbreg_autop.c +++ b/src/dbreg/dbreg_autop.c @@ -10,6 +10,23 @@ #include "dbinc/txn.h" /* + * PUBLIC: int __dbreg_register_42_print __P((ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__dbreg_register_42_print(env, dbtp, lsnp, notused2, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *info; +{ + COMPQUIET(notused2, DB_TXN_PRINT); + + return (__log_print_record(env, dbtp, lsnp, "__dbreg_register_42", __dbreg_register_42_desc, info)); +} + +/* * PUBLIC: int __dbreg_register_print __P((ENV *, DBT *, DB_LSN *, * PUBLIC: db_recops, void *)); */ diff --git a/src/dbreg/dbreg_rec.c b/src/dbreg/dbreg_rec.c index 1b387bb7..066efa03 100644 --- a/src/dbreg/dbreg_rec.c +++ b/src/dbreg/dbreg_rec.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. */ /* * Copyright (c) 1995, 1996 @@ -37,12 +37,16 @@ #include "db_config.h" #include "db_int.h" +#include "dbinc/blob.h" #include "dbinc/db_page.h" #include "dbinc/db_am.h" #include "dbinc/txn.h" static int __dbreg_open_file __P((ENV *, DB_TXN *, __dbreg_register_args *, void *)); +static int __dbreg_register_recover_int + __P((ENV *, DBT *, db_recops, void *, __dbreg_register_args *)); + /* * PUBLIC: int __dbreg_register_recover * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); @@ -56,21 +60,97 @@ __dbreg_register_recover(env, dbtp, lsnp, op, info) void *info; { __dbreg_register_args *argp; + int ret; + + argp = NULL; + + if ((ret = __dbreg_register_read(env, dbtp->data, &argp)) != 0) + goto out; + + ret = __dbreg_register_recover_int(env, dbtp, op, info, argp); + + if (ret == 0) + *lsnp = argp->prev_lsn; +out: if (argp != NULL) + __os_free(env, argp); + return (ret); +} + +/* + * PUBLIC: int __dbreg_register_42_recover + * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__dbreg_register_42_recover(env, dbtp, lsnp, op, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __dbreg_register_42_args *argp; + __dbreg_register_args arg; + int ret; + + argp = NULL; + if ((ret = __dbreg_register_42_read(env, dbtp->data, &argp)) != 0) + goto err; + + /* + * Databases before 6.0 cannot support blobs, so the blob_fid is 0. + * After 6.0 they can support blobs, so it is possible it has a non-0 + * blob_fid, but since logging that value in dbreg_register + * is only used in replication, and replication does not support blobs + * until 6.1, this is safe. + */ + memcpy(&arg, argp, sizeof(__dbreg_register_42_args)); + arg.blob_fid_lo = 0; + arg.blob_fid_hi = 0; + + ret = __dbreg_register_recover_int(env, dbtp, op, info, &arg); + + if (ret == 0) + *lsnp = argp->prev_lsn; +err: if (argp != NULL) + __os_free(env, argp); + return (ret); +} + +/* + * Internal register recovery function for both the 42 log version and the + * 61 log version. + */ +static int +__dbreg_register_recover_int(env, dbtp, op, info, argp) + ENV *env; + DBT *dbtp; + db_recops op; + void *info; + __dbreg_register_args *argp; +{ DB_ENTRY *dbe; DB_LOG *dblp; DB *dbp; u_int32_t opcode, status; int do_close, do_open, do_rem, ret, t_ret; +#ifdef HAVE_REPLICATION + DB_REP *db_rep; + DELAYED_BLOB_LIST *dbl; + int view_partial; + + dbl = NULL; +#endif dblp = env->lg_handle; dbp = NULL; + ret = 0; #ifdef DEBUG_RECOVER REC_PRINT(__dbreg_register_print); +#else + COMPQUIET(dbtp, NULL); #endif do_open = do_close = 0; - if ((ret = __dbreg_register_read(env, dbtp->data, &argp)) != 0) - goto out; opcode = FLD_ISSET(argp->opcode, DBREG_OP_MASK); switch (opcode) { @@ -123,12 +203,54 @@ __dbreg_register_recover(env, dbtp, lsnp, op, info) } if (do_open) { +#ifdef HAVE_REPLICATION + /* + * Partial replication may apply at this time. Invoke + * the callback if several conditions are met: + * - We are a view. + * - This is the OPENFILES pass of recovery. + * - The file is not a BDB owned database. + * - The dbreg operation is a create (id != TXN_INVALID). + * + * If the file is to be skipped, then we have to TXN_IGNORE + * the txnlist for that create operation. + */ + if (IS_VIEW_SITE(env) && op == DB_TXN_OPENFILES && + (!IS_DB_FILE(argp->name.data) || + IS_BLOB_META(argp->name.data)) && + argp->id != TXN_INVALID) { + db_rep = env->rep_handle; + /* + * Once a view, always a view. Must have set + * a callback already. + */ + if (db_rep->partial == NULL) { + __db_errx(env, DB_STR("1592", + "Must set a view callback.")); + ret = EINVAL; + goto out; + } + if ((ret = __rep_call_partial(env, + argp->name.data, &view_partial, 0, &dbl)) != 0) + goto out; + DB_ASSERT(env, dbl == NULL); + + /* + * If this should not be replicated, then set + * the child txnlist to TXN_IGNORE. + */ + if (view_partial == 0 && + (ret = __db_txnlist_update(env, info, + argp->id, TXN_IGNORE, NULL, &status, 1)) != 0) + goto out; + } +#endif /* * We must open the db even if the meta page is not * yet written as we may be creating subdatabase. */ - if (op == DB_TXN_OPENFILES && opcode != DBREG_CHKPNT - && opcode != DBREG_XCHKPNT) + if (op == DB_TXN_OPENFILES && opcode != DBREG_CHKPNT && + opcode != DBREG_XCHKPNT) F_SET(dblp, DBLOG_FORCE_OPEN); /* @@ -205,7 +327,7 @@ __dbreg_register_recover(env, dbtp, lsnp, op, info) if (dbe->dbp == NULL && !dbe->deleted) { /* No valid entry here. Nothing to do. */ MUTEX_UNLOCK(env, dblp->mtx_dbreg); - goto done; + goto out; } /* We have either an open entry or a deleted entry. */ @@ -273,11 +395,7 @@ __dbreg_register_recover(env, dbtp, lsnp, op, info) } } } -done: if (ret == 0) - *lsnp = argp->prev_lsn; -out: if (argp != NULL) - __os_free(env, argp); - return (ret); +out: return (ret); } /* @@ -296,11 +414,13 @@ __dbreg_open_file(env, txn, argp, info) DB *dbp; DB_ENTRY *dbe; DB_LOG *dblp; + db_seq_t blob_file_id; u_int32_t id, opcode, status; int ret; dblp = env->lg_handle; opcode = FLD_ISSET(argp->opcode, DBREG_OP_MASK); + ret = 0; /* * When we're opening, we have to check that the name we are opening @@ -336,7 +456,7 @@ __dbreg_open_file(env, txn, argp, info) * bit and try to open it again. */ if ((dbp = dbe->dbp) != NULL) { - if (opcode == DBREG_REOPEN || + if (opcode == DBREG_REOPEN || opcode == DBREG_XREOPEN || !F_ISSET(dbp, DB_AM_OPEN_CALLED) || dbp->meta_pgno != argp->meta_pgno || @@ -393,7 +513,11 @@ reopen: txn->mgrp = env->tx_handle; } - return (__dbreg_do_open(env, - txn, dblp, argp->uid.data, argp->name.data, argp->ftype, - argp->fileid, argp->meta_pgno, info, argp->id, opcode)); + GET_LO_HI(env, + argp->blob_fid_lo, argp->blob_fid_hi, blob_file_id, ret); + if (ret != 0) + return (ret); + return (__dbreg_do_open(env, txn, dblp, argp->uid.data, + argp->name.data, argp->ftype, argp->fileid, + argp->meta_pgno, info, argp->id, opcode, blob_file_id)); } diff --git a/src/dbreg/dbreg_stat.c b/src/dbreg/dbreg_stat.c index 6dfb3869..ad4bbdc2 100644 --- a/src/dbreg/dbreg_stat.c +++ b/src/dbreg/dbreg_stat.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/src/dbreg/dbreg_util.c b/src/dbreg/dbreg_util.c index 80de4d91..0d483f93 100644 --- a/src/dbreg/dbreg_util.c +++ b/src/dbreg/dbreg_util.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -9,6 +9,7 @@ #include "db_config.h" #include "db_int.h" +#include "dbinc/blob.h" #include "dbinc/db_page.h" #include "dbinc/db_am.h" #include "dbinc/fop.h" @@ -103,6 +104,7 @@ __dbreg_log_files(env, opcode) LOG *lp; u_int32_t lopcode; int ret; + u_int32_t blob_file_hi, blob_file_lo; dblp = env->lg_handle; lp = dblp->reginfo.primary; @@ -137,11 +139,12 @@ __dbreg_log_files(env, opcode) lopcode = opcode; if ( opcode == DBREG_CHKPNT && F_ISSET(fnp, DBREG_EXCL)) lopcode = DBREG_XCHKPNT; + SET_LO_HI_VAR(fnp->blob_file_id, blob_file_lo, blob_file_hi); if ((ret = __dbreg_register_log(env, NULL, &r_unused, F_ISSET(fnp, DB_FNAME_DURABLE) ? 0 : DB_LOG_NOT_DURABLE, lopcode | F_ISSET(fnp, DB_FNAME_DBREG_MASK), dbtp, &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno, - TXN_INVALID)) != 0) + TXN_INVALID, blob_file_lo, blob_file_hi)) != 0) break; } @@ -429,7 +432,7 @@ __dbreg_id_to_db(env, txn, dbpp, ndx, tryopen) if ((ret = __dbreg_do_open(env, txn, dblp, fname->ufid, name, fname->s_type, ndx, fname->meta_pgno, NULL, TXN_INVALID, F_ISSET(fname, DB_FNAME_INMEM) ? - DBREG_REOPEN : DBREG_OPEN)) != 0) + DBREG_REOPEN : DBREG_OPEN, fname->blob_file_id)) != 0) return (ret); *dbpp = dblp->dbentry[ndx].dbp; @@ -540,6 +543,53 @@ __dbreg_fid_to_fname(dblp, fid, have_lock, fnamep) } /* + * __dbreg_blob_file_to_fname -- + * Traverse the shared-memory list of database file names, looking for + * the entry that matches the passed blob file id. Returns 0 on success; + * -1 on error. + * + * PUBLIC: int __dbreg_blob_file_to_fname + * PUBLIC: __P((DB_LOG *, db_seq_t, int, FNAME **)); + */ +int +__dbreg_blob_file_to_fname(dblp, blob_file_id, have_lock, fnamep) + DB_LOG *dblp; + db_seq_t blob_file_id; + int have_lock; + FNAME **fnamep; +{ + ENV *env; + FNAME *fnp; + LOG *lp; + int ret; + + env = dblp->env; + lp = dblp->reginfo.primary; + + ret = -1; + + /* + * If blob_file is 0 then blobs are not enabled and the value is not + * unique. + */ + if (blob_file_id == 0) + return (ret); + + if (!have_lock) + MUTEX_LOCK(env, lp->mtx_filelist); + SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname) + if (fnp->blob_file_id == blob_file_id) { + *fnamep = fnp; + ret = 0; + break; + } + if (!have_lock) + MUTEX_UNLOCK(env, lp->mtx_filelist); + + return (ret); +} + +/* * __dbreg_get_name * * Interface to get name of registered files. This is mainly diagnostic @@ -577,14 +627,14 @@ __dbreg_get_name(env, fid, fnamep, dnamep) * is not protected by the thread mutex. * PUBLIC: int __dbreg_do_open __P((ENV *, * PUBLIC: DB_TXN *, DB_LOG *, u_int8_t *, char *, DBTYPE, - * PUBLIC: int32_t, db_pgno_t, void *, u_int32_t, u_int32_t)); + * PUBLIC: int32_t, db_pgno_t, void *, u_int32_t, u_int32_t, db_seq_t)); */ int -__dbreg_do_open(env, - txn, lp, uid, name, ftype, ndx, meta_pgno, info, id, opcode) +__dbreg_do_open(env, txn, + dblp, uid, name, ftype, ndx, meta_pgno, info, id, opcode, blob_file_id) ENV *env; DB_TXN *txn; - DB_LOG *lp; + DB_LOG *dblp; u_int8_t *uid; char *name; DBTYPE ftype; @@ -592,6 +642,7 @@ __dbreg_do_open(env, db_pgno_t meta_pgno; void *info; u_int32_t id, opcode; + db_seq_t blob_file_id; { DB *dbp; u_int32_t cstat, ret_stat; @@ -604,7 +655,7 @@ __dbreg_do_open(env, try_inmem = 0; retry_inmem: - if ((ret = __db_create_internal(&dbp, lp->env, 0)) != 0) + if ((ret = __db_create_internal(&dbp, dblp->env, 0)) != 0) return (ret); /* @@ -700,7 +751,7 @@ err: if (cstat == TXN_UNEXPECTED) * handling those cases specially, above. */ if (try_inmem == 0 && - opcode != DBREG_PREOPEN && opcode != DBREG_REOPEN && + opcode != DBREG_PREOPEN && opcode != DBREG_REOPEN && opcode != DBREG_XREOPEN) { if ((ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0) return (ret); @@ -725,6 +776,7 @@ err: if (cstat == TXN_UNEXPECTED) * we are closing a non-existent file and need to mark * it as deleted. */ + dbp->blob_file_id = blob_file_id; if (dbp->log_filename == NULL && (ret = __dbreg_setup(dbp, name, NULL, id)) != 0) return (ret); @@ -736,7 +788,8 @@ not_right: return (ret == 0 ? t_ret : ret); /* Add this file as deleted. */ - if ((t_ret = __dbreg_add_dbentry(env, lp, NULL, ndx)) != 0 && ret == 0) + if ((t_ret = __dbreg_add_dbentry(env, dblp, NULL, ndx)) != 0 && + ret == 0) ret = t_ret; return (ret); } |
