| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* archive.c - ldap ldbm back-end archive and restore entry points */
- #include "back-ldbm.h"
- int ldbm_back_archive2ldbm( Slapi_PBlock *pb )
- {
- struct ldbminfo *li;
- char *rawdirectory = NULL; /* -a <directory> */
- char *directory = NULL; /* normalized */
- char *backendname = NULL;
- int return_value = -1;
- int task_flags = 0;
- int run_from_cmdline = 0;
- Slapi_Task *task;
- int is_old_to_new = 0;
- slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
- slapi_pblock_get( pb, SLAPI_SEQ_VAL, &rawdirectory );
- slapi_pblock_get( pb, SLAPI_BACKEND_INSTANCE_NAME, &backendname);
- slapi_pblock_get( pb, SLAPI_BACKEND_TASK, &task );
- slapi_pblock_get( pb, SLAPI_TASK_FLAGS, &task_flags );
- li->li_flags = run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
- if ( !rawdirectory || !*rawdirectory ) {
- LDAPDebug( LDAP_DEBUG_ANY, "archive2db: no archive name\n",
- 0, 0, 0 );
- return( -1 );
- }
- directory = rel2abspath(rawdirectory);
- /* check the current idl format vs backup DB version */
- if (idl_get_idl_new())
- {
- char *dbversion = NULL;
- char *dataversion = NULL;
- int value = 0;
- if (dbversion_read(li, directory, &dbversion, &dataversion) != 0)
- {
- LDAPDebug(LDAP_DEBUG_ANY, "Warning: Unable to read dbversion "
- "file in %s\n", directory, 0, 0);
- }
- value = lookup_dbversion(dbversion, DBVERSION_TYPE);
- if (value & DBVERSION_OLD_IDL)
- {
- is_old_to_new = 1;
- }
- slapi_ch_free_string(&dbversion);
- slapi_ch_free_string(&dataversion);
- }
- /* No ldbm be's exist until we process the config information. */
- if (run_from_cmdline) {
- mapping_tree_init();
- ldbm_config_load_dse_info(li);
- } else {
- ldbm_instance *inst;
- Object *inst_obj, *inst_obj2;
- /* task does not support restore old idl onto new idl server */
- if (is_old_to_new)
- {
- LDAPDebug(LDAP_DEBUG_ANY,
- "backup has old idl format; "
- "to restore old formated backup onto the new server, "
- "please use command line utility \"bak2db\" .\n",
- 0, 0, 0);
- if (task)
- {
- slapi_task_log_notice(task,
- "backup has old idl format; "
- "to restore old formated backup onto the new server, "
- "please use command line utility \"bak2db\" .");
- }
- goto out;
- }
- /* server is up -- mark all backends busy */
- for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
- inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
- inst = (ldbm_instance *)object_get_data(inst_obj);
- /* check if an import/restore is already ongoing... */
- if (instance_set_busy(inst) != 0) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "ldbm: '%s' is already in the middle of "
- "another task and cannot be disturbed.\n",
- inst->inst_name, 0, 0);
- if (task) {
- slapi_task_log_notice(task,
- "Backend '%s' is already in the middle of "
- "another task and cannot be disturbed.",
- inst->inst_name);
- }
- /* painfully, we have to clear the BUSY flags on the
- * backends we'd already marked...
- */
- for (inst_obj2 = objset_first_obj(li->li_instance_set);
- inst_obj2 && (inst_obj2 != inst_obj);
- inst_obj2 = objset_next_obj(li->li_instance_set,
- inst_obj2)) {
- inst = (ldbm_instance *)object_get_data(inst_obj2);
- instance_set_not_busy(inst);
- }
- object_release(inst_obj2);
- object_release(inst_obj);
- goto out;
- }
- }
- /* now take down ALL BACKENDS */
- for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
- inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
- inst = (ldbm_instance *)object_get_data(inst_obj);
- LDAPDebug(LDAP_DEBUG_ANY, "Bringing %s offline...\n",
- inst->inst_name, 0, 0);
- if (task) {
- slapi_task_log_notice(task, "Bringing %s offline...",
- inst->inst_name);
- }
- slapi_mtn_be_disable(inst->inst_be);
- cache_clear(&inst->inst_cache);
- }
- /* now we know nobody's using any of the backend instances, so we
- * can shutdown the dblayer -- this closes all instances too.
- * Use DBLAYER_RESTORE_MODE to prevent loss of perfctr memory.
- */
- dblayer_close(li, DBLAYER_RESTORE_MODE);
- }
- /* tell the database to restore */
- return_value = dblayer_restore(li, directory, task, backendname);
- if (0 != return_value) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "archive2db: Failed to read backup file set. "
- "Either the directory specified doesn't exist, "
- "or it exists but doesn't contain a valid backup set, "
- "or file permissions prevent the server reading "
- "the backup set. error=%d (%s)\n",
- return_value, dblayer_strerror(return_value), 0 );
- if (task) {
- slapi_task_log_notice(task, "Failed to read the backup file set "
- "from %s", directory);
- }
- }
- if (run_from_cmdline)
- {
- if (is_old_to_new)
- {
- /* does not exist */
- char *p;
- char c;
- char *bakup_dir = NULL;
- int skipinit = SLAPI_UPGRADEDB_SKIPINIT;
- p = strrchr(directory, '/');
- if (NULL == p)
- {
- p = strrchr(directory, '\\');
- }
- if (NULL == p) /* never happen, I guess */
- {
- directory = ".";
- c = '/';
- }
- else
- {
- c = *p;
- *p = '\0';
- }
- bakup_dir = slapi_ch_smprintf("%s%ctmp_%010ld", directory, c, time(0));
- LDAPDebug( LDAP_DEBUG_ANY,
- "archive2db: backup dir: %s\n", bakup_dir, 0, 0);
- *p = c;
- slapi_pblock_set( pb, SLAPI_SEQ_VAL, bakup_dir );
- slapi_pblock_set( pb, SLAPI_SEQ_TYPE, &skipinit );
- return_value = ldbm_back_upgradedb( pb );
- }
- }
- else
- {
- ldbm_instance *inst;
- Object *inst_obj;
- int ret;
- if (0 != return_value) {
- /* error case (607331)
- * just to go back to the previous state if possible */
- dblayer_start(li, DBLAYER_NORMAL_MODE);
- }
- /* bring all backends back online */
- for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
- inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
- inst = (ldbm_instance *)object_get_data(inst_obj);
- ret = dblayer_instance_start(inst->inst_be, DBLAYER_NORMAL_MODE);
- if (ret != 0) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "archive2db: Unable to restart '%s'\n",
- inst->inst_name, 0, 0);
- if (task) {
- slapi_task_log_notice(task, "Unable to restart '%s'",
- inst->inst_name);
- }
- } else {
- slapi_mtn_be_enable(inst->inst_be);
- instance_set_not_busy(inst);
- }
- }
- }
- out:
- slapi_ch_free_string(&directory);
- return return_value;
- }
- int ldbm_back_ldbm2archive( Slapi_PBlock *pb )
- {
- struct ldbminfo *li;
- char *rawdirectory = NULL; /* -a <directory> */
- char *directory = NULL; /* normalized */
- char *dir_bak = NULL;
- int return_value = -1;
- int task_flags = 0;
- int run_from_cmdline = 0;
- Slapi_Task *task;
- struct stat sbuf;
- slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
- slapi_pblock_get( pb, SLAPI_SEQ_VAL, &rawdirectory );
- slapi_pblock_get( pb, SLAPI_TASK_FLAGS, &task_flags );
- li->li_flags = run_from_cmdline = (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE);
- slapi_pblock_get( pb, SLAPI_BACKEND_TASK, &task );
- if ( !rawdirectory || !*rawdirectory ) {
- LDAPDebug( LDAP_DEBUG_ANY, "db2archive: no archive name\n",
- 0, 0, 0 );
- return -1;
- }
- /* start the database code up, do not attempt to perform recovery */
- if (run_from_cmdline) {
- /* No ldbm be's exist until we process the config information. */
- mapping_tree_init();
- ldbm_config_load_dse_info(li);
- if (0 != (return_value =
- dblayer_start(li,
- DBLAYER_ARCHIVE_MODE|DBLAYER_NO_DBTHREADS_MODE))) {
- LDAPDebug(LDAP_DEBUG_ANY, "db2archive: Failed to init database\n",
- 0, 0, 0);
- if (task) {
- slapi_task_log_notice(task, "Failed to init database");
- }
- return -1;
- }
- }
- /* Initialize directory */
- directory = rel2abspath(rawdirectory);
- if (stat(directory, &sbuf) == 0) {
- int baklen = 0;
- if (slapd_comp_path(directory, li->li_directory) == 0) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "db2archive: Cannot archive to the db directory.\n", 0, 0, 0);
- if (task) {
- slapi_task_log_notice(task,
- "Cannot archive to the db directory.");
- }
- return_value = -1;
- goto out;
- }
- baklen = strlen(directory) + 5; /* ".bak\0" */
- dir_bak = slapi_ch_malloc(baklen);
- PR_snprintf(dir_bak, baklen, "%s.bak", directory);
- LDAPDebug(LDAP_DEBUG_ANY, "db2archive: %s exists. Renaming to %s\n",
- directory, dir_bak, 0);
- if (task) {
- slapi_task_log_notice(task, "%s exists. Renaming to %s",
- directory, dir_bak);
- }
- if (stat(dir_bak, &sbuf) == 0) {
- return_value = ldbm_delete_dirs(dir_bak);
- if (0 != return_value) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "db2archive: %s exists and failed to delete it.\n",
- dir_bak, 0, 0);
- if (task) {
- slapi_task_log_notice(task,
- "%s exists and failed to delete it.", dir_bak);
- }
- return_value = -1;
- goto out;
- }
- }
- return_value = PR_Rename(directory, dir_bak);
- if (return_value != PR_SUCCESS) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug(LDAP_DEBUG_ANY,
- "db2archive: Failed to rename \"%s\" to \"%s\".\n",
- directory, dir_bak, 0);
- LDAPDebug(LDAP_DEBUG_ANY,
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0);
- if (task) {
- slapi_task_log_notice(task,
- "Failed to rename \"%s\" to \"%s\".",
- directory, dir_bak);
- slapi_task_log_notice(task,
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)",
- prerr, slapd_pr_strerror(prerr));
- }
- return_value = -1;
- goto out;
- }
- }
- if (0 != MKDIR(directory,SLAPD_DEFAULT_DIR_MODE) && EEXIST != errno) {
- char *msg = dblayer_strerror(errno);
- LDAPDebug(LDAP_DEBUG_ANY,
- "db2archive: mkdir(%s) failed; errno %i (%s)\n",
- directory, errno, msg ? msg : "unknown");
- if (task) {
- slapi_task_log_notice(task,
- "mkdir(%s) failed; errno %i (%s)",
- directory, errno, msg ? msg : "unknown");
- }
- goto err;
- }
- /* to avoid conflict w/ import, do this check for commandline, as well */
- {
- Object *inst_obj, *inst_obj2;
- ldbm_instance *inst = NULL;
- /* server is up -- mark all backends busy */
- for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
- inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
- inst = (ldbm_instance *)object_get_data(inst_obj);
- /* check if an import/restore is already ongoing... */
- if (instance_set_busy(inst) != 0 || dblayer_in_import(inst) != 0) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "ldbm: '%s' is already in the middle of "
- "another task and cannot be disturbed.\n",
- inst->inst_name, 0, 0);
- if (task) {
- slapi_task_log_notice(task,
- "Backend '%s' is already in the middle of "
- "another task and cannot be disturbed.",
- inst->inst_name);
- }
- /* painfully, we have to clear the BUSY flags on the
- * backends we'd already marked...
- */
- for (inst_obj2 = objset_first_obj(li->li_instance_set);
- inst_obj2 && (inst_obj2 != inst_obj);
- inst_obj2 = objset_next_obj(li->li_instance_set,
- inst_obj2)) {
- inst = (ldbm_instance *)object_get_data(inst_obj2);
- instance_set_not_busy(inst);
- }
- object_release(inst_obj2);
- object_release(inst_obj);
- goto err;
- }
- }
- }
- /* tell it to archive */
- return_value = dblayer_backup(li, directory, task);
- if (! run_from_cmdline) {
- ldbm_instance *inst;
- Object *inst_obj;
- /* none of these backends are busy anymore */
- for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
- inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
- inst = (ldbm_instance *)object_get_data(inst_obj);
- instance_set_not_busy(inst);
- }
- }
- err:
- if (return_value != 0) {
- LDAPDebug(LDAP_DEBUG_ANY, "db2archive: Rename %s back to %s\n",
- dir_bak, directory, 0);
- if (task) {
- slapi_task_log_notice(task, "Rename %s back to %s",
- dir_bak, directory);
- }
- ldbm_delete_dirs(directory);
- PR_Rename(dir_bak, directory);
- }
- out:
- /* close the database down again */
- if (run_from_cmdline &&
- 0 != dblayer_close(li,DBLAYER_ARCHIVE_MODE|DBLAYER_NO_DBTHREADS_MODE)) {
- LDAPDebug(LDAP_DEBUG_ANY, "db2archive: Failed to close database\n",
- 0, 0, 0);
- if (task) {
- slapi_task_log_notice(task, "Failed to close database");
- }
- }
- slapi_ch_free_string(&dir_bak);
- slapi_ch_free_string(&directory);
- return return_value;
- }
|