<commit_before>/*
   Copyright (c) 2008-2009 Gluster, Inc. <http://www.gluster.com>
   This file is part of GlusterFS.

   GlusterFS 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; either version 3 of the License,
   or (at your option) any later version.

   GlusterFS 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, see
   <http://www.gnu.org/licenses/>.
*/

/* TODO: link(oldpath, newpath) fails if newpath already exists. DHT should
 *       delete the newpath if it gets EEXISTS from link() call.
 */
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif

#include "glusterfs.h"
#include "xlator.h"
#include "dht-common.h"
#include "defaults.h"


int
dht_rename_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
		    int32_t op_ret, int32_t op_errno, struct iatt *stbuf,
                    struct iatt *preoldparent, struct iatt *postoldparent,
                    struct iatt *prenewparent, struct iatt *postnewparent)
{
	dht_local_t  *local = NULL;
	int           this_call_cnt = 0;
	call_frame_t *prev = NULL;


	local = frame->local;
	prev = cookie;

	if (op_ret == -1) {
		/* TODO: undo the damage */

		gf_log (this->name, GF_LOG_DEBUG,
			"rename %s -> %s on %s failed (%s)",
			local->loc.path, local->loc2.path,
			prev->this->name, strerror (op_errno));

		local->op_ret   = op_ret;
		local->op_errno = op_errno;
	} else {
		/* TODO: construct proper stbuf for dir */
                /* 
                 * FIXME: is this the correct way to build stbuf and
                 * parent bufs?
                */
                dht_iatt_merge (this, &local->stbuf, stbuf, prev->this);
                dht_iatt_merge (this, &local->preoldparent, preoldparent,
                                prev->this);
                dht_iatt_merge (this, &local->postoldparent, postoldparent,
                                prev->this);
                dht_iatt_merge (this, &local->preparent, prenewparent,
                                prev->this);
                dht_iatt_merge (this, &local->postparent, postnewparent,
                                prev->this);
	}

	this_call_cnt = dht_frame_return (frame);
	if (is_last_call (this_call_cnt)) {
                local->stbuf.ia_ino = local->loc.inode->ino;

                local->preoldparent.ia_ino = local->loc.parent->ino;
                local->postoldparent.ia_ino = local->loc.parent->ino;

                local->preparent.ia_ino = local->loc2.parent->ino;
                local->postparent.ia_ino = local->loc2.parent->ino;

                WIPE (&local->preoldparent);
                WIPE (&local->postoldparent);
                WIPE (&local->preparent);
                WIPE (&local->postparent);

		DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno,
				  &local->stbuf, &local->preoldparent,
                                  &local->postoldparent,
                                  &local->preparent, &local->postparent);
	}

	return 0;
}



int
dht_rename_dir_do (call_frame_t *frame, xlator_t *this)
{
	dht_local_t  *local = NULL;
	dht_conf_t   *conf = NULL;
	int           i = 0;

	conf = this->private;
	local = frame->local;

	if (local->op_ret == -1)
		goto err;

	local->call_cnt = conf->subvolume_cnt;
	local->op_ret = 0;

	for (i = 0; i < conf->subvolume_cnt; i++) {
		STACK_WIND (frame, dht_rename_dir_cbk,
			    conf->subvolumes[i],
			    conf->subvolumes[i]->fops->rename,
			    &local->loc, &local->loc2);
	}

	return 0;

err:
	DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno, NULL, NULL,
                          NULL, NULL, NULL);
	return 0;
}


int
dht_rename_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
			int op_ret, int op_errno, gf_dirent_t *entries)
{
	dht_local_t  *local = NULL;
	int           this_call_cnt = -1;
	call_frame_t *prev = NULL;

	local = frame->local;
	prev  = cookie;

	if (op_ret > 2) {
		gf_log (this->name, GF_LOG_TRACE,
			"readdir on %s for %s returned %d entries",
			prev->this->name, local->loc.path, op_ret);
		local->op_ret = -1;
		local->op_errno = ENOTEMPTY;
	}

	this_call_cnt = dht_frame_return (frame);

	if (is_last_call (this_call_cnt)) {
		dht_rename_dir_do (frame, this);
	}

	return 0;
}


int
dht_rename_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
			int op_ret, int op_errno, fd_t *fd)
{
	dht_local_t  *local = NULL;
	int           this_call_cnt = -1;
	call_frame_t *prev = NULL;


	local = frame->local;
	prev  = cookie;

	if (op_ret == -1) {
		gf_log (this->name, GF_LOG_DEBUG,
			"opendir on %s for %s failed (%s)",
			prev->this->name, local->loc.path,
			strerror (op_errno));
		goto err;
	}

	STACK_WIND (frame, dht_rename_readdir_cbk,
		    prev->this, prev->this->fops->readdir,
		    local->fd, 4096, 0);

	return 0;

err:
	this_call_cnt = dht_frame_return (frame);

	if (is_last_call (this_call_cnt)) {
		dht_rename_dir_do (frame, this);
	}

	return 0;
}


int
dht_rename_dir (call_frame_t *frame, xlator_t *this)
{
	dht_conf_t  *conf = NULL;
	dht_local_t *local = NULL;
	int          i = 0;
	int          op_errno = -1;


	conf = frame->this->private;
	local = frame->local;

	local->call_cnt = conf->subvolume_cnt;

	local->fd = fd_create (local->loc.inode, frame->root->pid);
	if (!local->fd) {
		gf_log (this->name, GF_LOG_ERROR,
			"Out of memory");
		op_errno = ENOMEM;
		goto err;
	}

	local->op_ret = 0;

	if (!local->dst_cached) {
		dht_rename_dir_do (frame, this);
		return 0;
	}

	for (i = 0; i < conf->subvolume_cnt; i++) {
		STACK_WIND (frame, dht_rename_opendir_cbk,
			    conf->subvolumes[i],
			    conf->subvolumes[i]->fops->opendir,
			    &local->loc2, local->fd);
	}

	return 0;

err:
	op_errno = (op_errno == -1) ? errno : op_errno;
	DHT_STACK_UNWIND (rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL);
	return 0;
}<commit_msg>Check whether a server is down before calling rename on the directory<commit_after>/*
   Copyright (c) 2008-2009 Gluster, Inc. <http://www.gluster.com>
   This file is part of GlusterFS.

   GlusterFS 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; either version 3 of the License,
   or (at your option) any later version.

   GlusterFS 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, see
   <http://www.gnu.org/licenses/>.
*/

/* TODO: link(oldpath, newpath) fails if newpath already exists. DHT should
 *       delete the newpath if it gets EEXISTS from link() call.
 */
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif

#include "glusterfs.h"
#include "xlator.h"
#include "dht-common.h"
#include "defaults.h"


int
dht_rename_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
		    int32_t op_ret, int32_t op_errno, struct iatt *stbuf,
                    struct iatt *preoldparent, struct iatt *postoldparent,
                    struct iatt *prenewparent, struct iatt *postnewparent)
{
	dht_local_t  *local = NULL;
	int           this_call_cnt = 0;
	call_frame_t *prev = NULL;


	local = frame->local;
	prev = cookie;

	if (op_ret == -1) {
		/* TODO: undo the damage */

		gf_log (this->name, GF_LOG_DEBUG,
			"rename %s -> %s on %s failed (%s)",
			local->loc.path, local->loc2.path,
			prev->this->name, strerror (op_errno));

		local->op_ret   = op_ret;
		local->op_errno = op_errno;
	} else {
		/* TODO: construct proper stbuf for dir */
                /* 
                 * FIXME: is this the correct way to build stbuf and
                 * parent bufs?
                */
                dht_iatt_merge (this, &local->stbuf, stbuf, prev->this);
                dht_iatt_merge (this, &local->preoldparent, preoldparent,
                                prev->this);
                dht_iatt_merge (this, &local->postoldparent, postoldparent,
                                prev->this);
                dht_iatt_merge (this, &local->preparent, prenewparent,
                                prev->this);
                dht_iatt_merge (this, &local->postparent, postnewparent,
                                prev->this);
	}

	this_call_cnt = dht_frame_return (frame);
	if (is_last_call (this_call_cnt)) {
                local->stbuf.ia_ino = local->loc.inode->ino;

                local->preoldparent.ia_ino = local->loc.parent->ino;
                local->postoldparent.ia_ino = local->loc.parent->ino;

                local->preparent.ia_ino = local->loc2.parent->ino;
                local->postparent.ia_ino = local->loc2.parent->ino;

                WIPE (&local->preoldparent);
                WIPE (&local->postoldparent);
                WIPE (&local->preparent);
                WIPE (&local->postparent);

		DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno,
				  &local->stbuf, &local->preoldparent,
                                  &local->postoldparent,
                                  &local->preparent, &local->postparent);
	}

	return 0;
}



int
dht_rename_dir_do (call_frame_t *frame, xlator_t *this)
{
	dht_local_t  *local = NULL;
	dht_conf_t   *conf = NULL;
	int           i = 0;

	conf = this->private;
	local = frame->local;

	if (local->op_ret == -1)
		goto err;

	local->call_cnt = conf->subvolume_cnt;
	local->op_ret = 0;

	for (i = 0; i < conf->subvolume_cnt; i++) {
		STACK_WIND (frame, dht_rename_dir_cbk,
			    conf->subvolumes[i],
			    conf->subvolumes[i]->fops->rename,
			    &local->loc, &local->loc2);
	}

	return 0;

err:
	DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno, NULL, NULL,
                          NULL, NULL, NULL);
	return 0;
}


int
dht_rename_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
			int op_ret, int op_errno, gf_dirent_t *entries)
{
	dht_local_t  *local = NULL;
	int           this_call_cnt = -1;
	call_frame_t *prev = NULL;

	local = frame->local;
	prev  = cookie;

	if (op_ret > 2) {
		gf_log (this->name, GF_LOG_TRACE,
			"readdir on %s for %s returned %d entries",
			prev->this->name, local->loc.path, op_ret);
		local->op_ret = -1;
		local->op_errno = ENOTEMPTY;
	}

	this_call_cnt = dht_frame_return (frame);

	if (is_last_call (this_call_cnt)) {
		dht_rename_dir_do (frame, this);
	}

	return 0;
}


int
dht_rename_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
			int op_ret, int op_errno, fd_t *fd)
{
	dht_local_t  *local = NULL;
	int           this_call_cnt = -1;
	call_frame_t *prev = NULL;


	local = frame->local;
	prev  = cookie;

	if (op_ret == -1) {
		gf_log (this->name, GF_LOG_DEBUG,
			"opendir on %s for %s failed (%s)",
			prev->this->name, local->loc.path,
			strerror (op_errno));
		goto err;
	}

	STACK_WIND (frame, dht_rename_readdir_cbk,
		    prev->this, prev->this->fops->readdir,
		    local->fd, 4096, 0);

	return 0;

err:
	this_call_cnt = dht_frame_return (frame);

	if (is_last_call (this_call_cnt)) {
		dht_rename_dir_do (frame, this);
	}

	return 0;
}


int
dht_rename_dir (call_frame_t *frame, xlator_t *this)
{
	dht_conf_t  *conf = NULL;
	dht_local_t *local = NULL;
	int          i = 0;
	int          op_errno = -1;


	conf = frame->this->private;
	local = frame->local;

	local->call_cnt = conf->subvolume_cnt;

        for (i = 0; i < conf->subvolume_cnt; i++) {
                if (!conf->subvolume_status[i]) {
                        op_errno = ENOTCONN;
                        goto err;
                }
        }

	local->fd = fd_create (local->loc.inode, frame->root->pid);
	if (!local->fd) {
		gf_log (this->name, GF_LOG_ERROR,
			"Out of memory");
		op_errno = ENOMEM;
		goto err;
	}

	local->op_ret = 0;

	if (!local->dst_cached) {
		dht_rename_dir_do (frame, this);
		return 0;
	}

	for (i = 0; i < conf->subvolume_cnt; i++) {
		STACK_WIND (frame, dht_rename_opendir_cbk,
			    conf->subvolumes[i],
			    conf->subvolumes[i]->fops->opendir,
			    &local->loc2, local->fd);
	}

	return 0;

err:
	op_errno = (op_errno == -1) ? errno : op_errno;
	DHT_STACK_UNWIND (rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL);
	return 0;
}
{'fraction_non_alphanumeric': 0.12365761212886923, 'fraction_numerical': 0.007817435249526217, 'mean_word_length': 2.49090407938258, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 205, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7374742', 'n_tokens_mistral': 4853, 'n_tokens_neox': 4502, 'n_words': 1135}