text:
#include <linux/major.h>

#include <linux/blkdev.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/mutex.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <linux/net.h>
#include <linux/kthread.h>

#include <asm/uaccess.h>
#include <asm/types.h>

#include <linux/nbd.h>

#define NBD_MAGIC 0x68797548

#ifdef NDEBUG
#define dprintk(flags, fmt...)
#else /* NDEBUG */
#define dprintk(flags, fmt...) do { \
	if (debugflags & (flags)) printk(KERN_DEBUG fmt); \
} while (0)
#define DBG_IOCTL       0x0004
#define DBG_INIT        0x0010
#define DBG_EXIT        0x0020
#define DBG_BLKDEV      0x0100
#define DBG_RX          0x0200
#define DBG_TX          0x0400
static unsigned int debugflags;
#endif /* NDEBUG */

static unsigned int nbds_max = 16;
static struct nbd_device *nbd_dev;
static int max_part;

/*
 * Use just one lock (or at most 1 per NIC). Two arguments for this:
 * 1. Each NIC is essentially a synchronization point for all servers
 *    accessed through that NIC so there's no need to have more locks
 *    than NICs anyway.
 * 2. More locks lead to more "Dirty cache line bouncing" which will slow
 *    down each lock to the point where they're actually slower than just
 *    a single lock.
 * Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this!
 */
static DEFINE_SPINLOCK(nbd_lock);

#ifndef NDEBUG
static const char *ioctl_cmd_to_ascii(int cmd)
{
	switch (cmd) {
	case NBD_SET_SOCK: return "set-sock";
	case NBD_SET_BLKSIZE: return "set-blksize";
	case NBD_SET_SIZE: return "set-size";
	case NBD_DO_IT: return "do-it";
	case NBD_CLEAR_SOCK: return "clear-sock";
	case NBD_CLEAR_QUE: return "clear-que";
	case NBD_PRINT_DEBUG: return "print-debug";
	case NBD_SET_SIZE_BLOCKS: return "set-size-blocks";
	case NBD_DISCONNECT: return "disconnect";
	case BLKROSET: return "set-read-only";
	case BLKFLSBUF: return "flush-buffer-cache";
	}
	return "unknown";
}

static const char *nbdcmd_to_ascii(int cmd)
{
	switch (cmd) {
	case  NBD_CMD_READ: return "read";
	case NBD_CMD_WRITE: return "write";
	case  NBD_CMD_DISC: return "disconnect";
	}
	return "invalid";
}
#endif /* NDEBUG */

static void nbd_end_request(struct request *req)
{
	int error = req->errors ? -EIO : 0;
	struct request_queue *q = req->q;
	unsigned long flags;

	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
			req, error ? "failed" : "done");

	spin_lock_irqsave(q->queue_lock, flags);
	__blk_end_request_all(req, error);
	spin_unlock_irqrestore(q->queue_lock, flags);
}

static void sock_shutdown(struct nbd_device *nbd, int lock)
{
	/* Forcibly shutdown the socket causing all listeners
	 * to error
	 *
	 * FIXME: This code is duplicated from sys_shutdown, but
	 * there should be a more generic interface rather than
	 * calling socket ops directly here */
	if (lock)
		mutex_lock(&nbd->tx_lock);
	if (nbd->sock) {
		dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
		kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
		nbd->sock = NULL;
	}
	if (lock)
		mutex_unlock(&nbd->tx_lock);
}

static void nbd_xmit_timeout(unsigned long arg)
{
	struct task_struct *task = (struct task_struct *)arg;

	printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d)\n",
		task->comm, task->pid);
	force_sig(SIGKILL, task);
}

/*
 *  Send or receive packet.
 */
static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
		int msg_flags)
{
	struct socket *sock = nbd->sock;
	int result;
	struct msghdr msg;
	struct kvec iov;
	sigset_t blocked, oldset;

	if (unlikely(!sock)) {
		dev_err(disk_to_dev(nbd->disk),
			"Attempted %s on closed socket in sock_xmit\n",
			(send ? "send" : "recv"));
		return -EINVAL;
	}

	/* Allow interception of SIGKILL only
	 * Don't allow other signals to interrupt the transmission */
	siginitsetinv(&blocked, sigmask(SIGKILL));
	sigprocmask(SIG_SETMASK, &blocked, &oldset);

	do {
		sock->sk->sk_allocation = GFP_NOIO;
		iov.iov_base = buf;
		iov.iov_len = size;
		msg.msg_name = NULL;
		msg.msg_namelen = 0;
		msg.msg_control = NULL;
		msg.msg_controllen = 0;
		msg.msg_flags = msg_flags | MSG_NOSIGNAL;

		if (send) {
			struct timer_list ti;

			if (nbd->xmit_timeout) {
				init_timer(&ti);
				ti.function = nbd_xmit_timeout;
				ti.data = (unsigned long)current;
				ti.expires = jiffies + nbd->xmit_timeout;
				add_timer(&ti);
			}
			result = kernel_sendmsg(sock, &msg, &iov, 1, size);
			if (nbd->xmit_timeout)
				del_timer_sync(&ti);
		} else
			result = kernel_recvmsg(sock, &msg, &iov, 1, size,
						msg.msg_flags);

		if (signal_pending(current)) {
			siginfo_t info;
			printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
				task_pid_nr(current), current->comm,
				dequeue_signal_lock(current, &current->blocked, &info));
			result = -EINTR;
			sock_shutdown(nbd, !send);
			break;
		}

		if (result <= 0) {
			if (result == 0)
				result = -EPIPE; /* short read */
			break;
		}
		size -= result;
		buf += result;
	} while (size > 0);

	sigprocmask(SIG_SETMASK, &oldset, NULL);

	return result;
}

static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec,
		int flags)
{
	int result;
	void *kaddr = kmap(bvec->bv_page);
	result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset,
			   bvec->bv_len, flags);
	kunmap(bvec->bv_page);
	return result;
}

/* always call with the tx_lock held */
static int nbd_send_req(struct nbd_device *nbd, struct request *req)
{
	int result, flags;
	struct nbd_request request;
	unsigned long size = blk_rq_bytes(req);

	request.magic = htonl(NBD_REQUEST_MAGIC);
	request.type = htonl(nbd_cmd(req));
	request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
	request.len = htonl(size);
	memcpy(request.handle, &req, sizeof(req));

	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n",
			nbd->disk->disk_name, req,
			nbdcmd_to_ascii(nbd_cmd(req)),
			(unsigned long long)blk_rq_pos(req) << 9,
			blk_rq_bytes(req));
	result = sock_xmit(nbd, 1, &request, sizeof(request),
			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
	if (result <= 0) {
		dev_err(disk_to_dev(nbd->disk),
			"Send control failed (result %d)\n", result);
		goto error_out;
	}

	if (nbd_cmd(req) == NBD_CMD_WRITE) {
		struct req_iterator iter;
		struct bio_vec *bvec;
		/*
		 * we are really probing at internals to determine
		 * whether to set MSG_MORE or not...
		 */
		rq_for_each_segment(bvec, req, iter) {
			flags = 0;
			if (!rq_iter_last(req, iter))
				flags = MSG_MORE;
			dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
					nbd->disk->disk_name, req, bvec->bv_len);
			result = sock_send_bvec(nbd, bvec, flags);
			if (result <= 0) {
				dev_err(disk_to_dev(nbd->disk),
					"Send data failed (result %d)\n",
					result);
				goto error_out;
			}
		}
	}
	return 0;

error_out:
	return -EIO;
}

static struct request *nbd_find_request(struct nbd_device *nbd,
					struct request *xreq)
{
	struct request *req, *tmp;
	int err;

	err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq);
	if (unlikely(err))
		goto out;

	spin_lock(&nbd->queue_lock);
	list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) {
		if (req != xreq)
			continue;
		list_del_init(&req->queuelist);
		spin_unlock(&nbd->queue_lock);
		return req;
	}
	spin_unlock(&nbd->queue_lock);

	err = -ENOENT;

out:
	return ERR_PTR(err);
}

static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
{
	int result;
	void *kaddr = kmap(bvec->bv_page);
	result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
			MSG_WAITALL);
	kunmap(bvec->bv_page);
	return result;
}

/* NULL returned = something went wrong, inform userspace */
static struct request *nbd_read_stat(struct nbd_device *nbd)
{
	int result;
	struct nbd_reply reply;
	struct request *req;

	reply.magic = 0;
	result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
	if (result <= 0) {
		dev_err(disk_to_dev(nbd->disk),
			"Receive control failed (result %d)\n", result);
		goto harderror;
	}

	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
		dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)\n",
				(unsigned long)ntohl(reply.magic));
		result = -EPROTO;
		goto harderror;
	}

	req = nbd_find_request(nbd, *(struct request **)reply.handle);
	if (IS_ERR(req)) {
		result = PTR_ERR(req);
		if (result != -ENOENT)
			goto harderror;

		dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p)\n",
			reply.handle);
		result = -EBADR;
		goto harderror;
	}

	if (ntohl(reply.error)) {
		dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
			ntohl(reply.error));
		req->errors++;
		return req;
	}

	dprintk(DBG_RX, "%s: request %p: got reply\n",
			nbd->disk->disk_name, req);
	if (nbd_cmd(req) == NBD_CMD_READ) {
		struct req_iterator iter;
		struct bio_vec *bvec;

		rq_for_each_segment(bvec, req, iter) {
			result = sock_recv_bvec(nbd, bvec);
			if (result <= 0) {
				dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
					result);
				req->errors++;
				return req;
			}
			dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
				nbd->disk->disk_name, req, bvec->bv_len);
		}
	}
	return req;
harderror:
	nbd->harderror = result;
	return NULL;
}

static ssize_t pid_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	struct gendisk *disk = dev_to_disk(dev);

	return sprintf(buf, "%ld\n",
		(long) ((struct nbd_device *)disk->private_data)->pid);
}

static struct device_attribute pid_attr = {
	.attr = { .name = "pid", .mode = S_IRUGO},
	.show = pid_show,
};

static int nbd_do_it(struct nbd_device *nbd)
{
	struct request *req;
	int ret;

	BUG_ON(nbd->magic != NBD_MAGIC);

	nbd->pid = task_pid_nr(current);
	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
	if (ret) {
		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
		nbd->pid = 0;
		return ret;
	}

	while ((req = nbd_read_stat(nbd)) != NULL)
		nbd_end_request(req);

	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
	nbd->pid = 0;
	return 0;
}

static void nbd_clear_que(struct nbd_device *nbd)
{
	struct request *req;

	BUG_ON(nbd->magic != NBD_MAGIC);

	/*
	 * Because we have set nbd->sock to NULL under the tx_lock, all
	 * modifications to the list must have completed by now.  For
	 * the same reason, the active_req must be NULL.
	 *
	 * As a consequence, we don't need to take the spin lock while
	 * purging the list here.
	 */
	BUG_ON(nbd->sock);
	BUG_ON(nbd->active_req);

	while (!list_empty(&nbd->queue_head)) {
		req = list_entry(nbd->queue_head.next, struct request,
				 queuelist);
		list_del_init(&req->queuelist);
		req->errors++;
		nbd_end_request(req);
	}

	while (!list_empty(&nbd->waiting_queue)) {
		req = list_entry(nbd->waiting_queue.next, struct request,
				 queuelist);
		list_del_init(&req->queuelist);
		req->errors++;
		nbd_end_request(req);
	}
}

static void nbd_handle_req(struct nbd_device *nbd, struct request *req)
{
	if (req->cmd_type != REQ_TYPE_FS)
		goto error_out;

	nbd_cmd(req) = NBD_CMD_READ;
	if (rq_data_dir(req) == WRITE) {
		nbd_cmd(req) = NBD_CMD_WRITE;
		if (nbd->flags & NBD_READ_ONLY) {
			dev_err(disk_to_dev(nbd->disk),
				"Write on read-only\n");
			goto error_out;
		}
	}

	req->errors = 0;

	mutex_lock(&nbd->tx_lock);
	if (unlikely(!nbd->sock)) {
		mutex_unlock(&nbd->tx_lock);
		dev_err(disk_to_dev(nbd->disk),
			"Attempted send on closed socket\n");
		goto error_out;
	}

	nbd->active_req = req;

	if (nbd_send_req(nbd, req) != 0) {
		dev_err(disk_to_dev(nbd->disk), "Request send failed\n");
		req->errors++;
		nbd_end_request(req);
	} else {
		spin_lock(&nbd->queue_lock);
		list_add(&req->queuelist, &nbd->queue_head);
		spin_unlock(&nbd->queue_lock);
	}

	nbd->active_req = NULL;
	mutex_unlock(&nbd->tx_lock);
	wake_up_all(&nbd->active_wq);

	return;

error_out:
	req->errors++;
	nbd_end_request(req);
}

static int nbd_thread(void *data)
{
	struct nbd_device *nbd = data;
	struct request *req;

	set_user_nice(current, -20);
	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
		/* wait for something to do */
		wait_event_interruptible(nbd->waiting_wq,
					 kthread_should_stop() ||
					 !list_empty(&nbd->waiting_queue));

		/* extract request */
		if (list_empty(&nbd->waiting_queue))
			continue;

		spin_lock_irq(&nbd->queue_lock);
		req = list_entry(nbd->waiting_queue.next, struct request,
				 queuelist);
		list_del_init(&req->queuelist);
		spin_unlock_irq(&nbd->queue_lock);

		/* handle request */
		nbd_handle_req(nbd, req);
	}
	return 0;
}

/*
 * We always wait for result of write, for now. It would be nice to make it optional
 * in future
 * if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK))
 *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
 */

static void do_nbd_request(struct request_queue *q)
{
	struct request *req;

	while ((req = blk_fetch_request(q)) != NULL) {
		struct nbd_device *nbd;

		spin_unlock_irq(q->queue_lock);

		dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
				req->rq_disk->disk_name, req, req->cmd_type);

		nbd = req->rq_disk->private_data;

		BUG_ON(nbd->magic != NBD_MAGIC);

		if (unlikely(!nbd->sock)) {
			dev_err(disk_to_dev(nbd->disk),
				"Attempted send on closed socket\n");
			req->errors++;
			nbd_end_request(req);
			spin_lock_irq(q->queue_lock);
			continue;
		}

		spin_lock_irq(&nbd->queue_lock);
		list_add_tail(&req->queuelist, &nbd->waiting_queue);
		spin_unlock_irq(&nbd->queue_lock);

		wake_up(&nbd->waiting_wq);

		spin_lock_irq(q->queue_lock);
	}
}

/* Must be called with tx_lock held */

static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
		       unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case NBD_DISCONNECT: {
		struct request sreq;

		dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");

		blk_rq_init(NULL, &sreq);
		sreq.cmd_type = REQ_TYPE_SPECIAL;
		nbd_cmd(&sreq) = NBD_CMD_DISC;
		if (!nbd->sock)
			return -EINVAL;
		nbd_send_req(nbd, &sreq);
                return 0;
	}

	case NBD_CLEAR_SOCK: {
		struct file *file;

		nbd->sock = NULL;
		file = nbd->file;
		nbd->file = NULL;
		nbd_clear_que(nbd);
		BUG_ON(!list_empty(&nbd->queue_head));
		BUG_ON(!list_empty(&nbd->waiting_queue));
		if (file)
			fput(file);
		return 0;
	}

	case NBD_SET_SOCK: {
		struct file *file;
		if (nbd->file)
			return -EBUSY;
		file = fget(arg);
		if (file) {
			struct inode *inode = file->f_path.dentry->d_inode;
			if (S_ISSOCK(inode->i_mode)) {
				nbd->file = file;
				nbd->sock = SOCKET_I(inode);
				if (max_part > 0)
					bdev->bd_invalidated = 1;
				return 0;
			} else {
				fput(file);
			}
		}
		return -EINVAL;
	}

	case NBD_SET_BLKSIZE:
		nbd->blksize = arg;
		nbd->bytesize &= ~(nbd->blksize-1);
		bdev->bd_inode->i_size = nbd->bytesize;
		set_blocksize(bdev, nbd->blksize);
		set_capacity(nbd->disk, nbd->bytesize >> 9);
		return 0;

	case NBD_SET_SIZE:
		nbd->bytesize = arg & ~(nbd->blksize-1);
		bdev->bd_inode->i_size = nbd->bytesize;
		set_blocksize(bdev, nbd->blksize);
		set_capacity(nbd->disk, nbd->bytesize >> 9);
		return 0;

	case NBD_SET_TIMEOUT:
		nbd->xmit_timeout = arg * HZ;
		return 0;

	case NBD_SET_SIZE_BLOCKS:
		nbd->bytesize = ((u64) arg) * nbd->blksize;
		bdev->bd_inode->i_size = nbd->bytesize;
		set_blocksize(bdev, nbd->blksize);
		set_capacity(nbd->disk, nbd->bytesize >> 9);
		return 0;

	case NBD_DO_IT: {
		struct task_struct *thread;
		struct file *file;
		int error;

		if (nbd->pid)
			return -EBUSY;
		if (!nbd->file)
			return -EINVAL;

		mutex_unlock(&nbd->tx_lock);

		thread = kthread_create(nbd_thread, nbd, "%s",
					nbd->disk->disk_name);
		if (IS_ERR(thread)) {
			mutex_lock(&nbd->tx_lock);
			return PTR_ERR(thread);
		}
		wake_up_process(thread);
		error = nbd_do_it(nbd);
		kthread_stop(thread);

		mutex_lock(&nbd->tx_lock);
		if (error)
			return error;
		sock_shutdown(nbd, 0);
		file = nbd->file;
		nbd->file = NULL;
		nbd_clear_que(nbd);
		dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
		if (file)
			fput(file);
		nbd->bytesize = 0;
		bdev->bd_inode->i_size = 0;
		set_capacity(nbd->disk, 0);
		if (max_part > 0)
			ioctl_by_bdev(bdev, BLKRRPART, 0);
		return nbd->harderror;
	}

	case NBD_CLEAR_QUE:
		/*
		 * This is for compatibility only.  The queue is always cleared
		 * by NBD_DO_IT or NBD_CLEAR_SOCK.
		 */
		BUG_ON(!nbd->sock && !list_empty(&nbd->queue_head));
		return 0;

	case NBD_PRINT_DEBUG:
		dev_info(disk_to_dev(nbd->disk),
			"next = %p, prev = %p, head = %p\n",
			nbd->queue_head.next, nbd->queue_head.prev,
			&nbd->queue_head);
		return 0;
	}
	return -ENOTTY;
}

static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
		     unsigned int cmd, unsigned long arg)
{
	struct nbd_device *nbd = bdev->bd_disk->private_data;
	int error;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	BUG_ON(nbd->magic != NBD_MAGIC);

	/* Anyone capable of this syscall can do *real bad* things */
	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
		nbd->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);

	mutex_lock(&nbd->tx_lock);
	error = __nbd_ioctl(bdev, nbd, cmd, arg);
	mutex_unlock(&nbd->tx_lock);

	return error;
}

static const struct block_device_operations nbd_fops =
{
	.owner =	THIS_MODULE,
	.ioctl =	nbd_ioctl,
};

/*
 * And here should be modules and kernel interface
 *  (Just smiley confuses emacs :-)
 */

static int __init nbd_init(void)
{
	int err = -ENOMEM;
	int i;
	int part_shift;

	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);

	if (max_part < 0) {
		printk(KERN_ERR "nbd: max_part must be >= 0\n");
		return -EINVAL;
	}

	nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
	if (!nbd_dev)
		return -ENOMEM;

	part_shift = 0;
	if (max_part > 0) {
		part_shift = fls(max_part);

		/*
		 * Adjust max_part according to part_shift as it is exported
		 * to user space so that user can know the max number of
		 * partition kernel should be able to manage.
		 *
		 * Note that -1 is required because partition 0 is reserved
		 * for the whole disk.
		 */
		max_part = (1UL << part_shift) - 1;
	}

	if ((1UL << part_shift) > DISK_MAX_PARTS)
		return -EINVAL;

	if (nbds_max > 1UL << (MINORBITS - part_shift))
		return -EINVAL;

	for (i = 0; i < nbds_max; i++) {
		struct gendisk *disk = alloc_disk(1 << part_shift);
		if (!disk)
			goto out;
		nbd_dev[i].disk = disk;
		/*
		 * The new linux 2.5 block layer implementation requires
		 * every gendisk to have its very own request_queue struct.
		 * These structs are big so we dynamically allocate them.
		 */
		disk->queue = blk_init_queue(do_nbd_request, &nbd_lock);
		if (!disk->queue) {
			put_disk(disk);
			goto out;
		}
		/*
		 * Tell the block layer that we are not a rotational device
		 */
		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
	}

	if (register_blkdev(NBD_MAJOR, "nbd")) {
		err = -EIO;
		goto out;
	}

	printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
	dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);

	for (i = 0; i < nbds_max; i++) {
		struct gendisk *disk = nbd_dev[i].disk;
		nbd_dev[i].file = NULL;
		nbd_dev[i].magic = NBD_MAGIC;
		nbd_dev[i].flags = 0;
		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
		spin_lock_init(&nbd_dev[i].queue_lock);
		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
		mutex_init(&nbd_dev[i].tx_lock);
		init_waitqueue_head(&nbd_dev[i].active_wq);
		init_waitqueue_head(&nbd_dev[i].waiting_wq);
		nbd_dev[i].blksize = 1024;
		nbd_dev[i].bytesize = 0;
		disk->major = NBD_MAJOR;
		disk->first_minor = i << part_shift;
		disk->fops = &nbd_fops;
		disk->private_data = &nbd_dev[i];
		sprintf(disk->disk_name, "nbd%d", i);
		set_capacity(disk, 0);
		add_disk(disk);
	}

	return 0;
out:
	while (i--) {
		blk_cleanup_queue(nbd_dev[i].disk->queue);
		put_disk(nbd_dev[i].disk);
	}
	kfree(nbd_dev);
	return err;
}

static void __exit nbd_cleanup(void)
{
	int i;
	for (i = 0; i < nbds_max; i++) {
		struct gendisk *disk = nbd_dev[i].disk;
		nbd_dev[i].magic = 0;
		if (disk) {
			del_gendisk(disk);
			blk_cleanup_queue(disk->queue);
			put_disk(disk);
		}
	}
	unregister_blkdev(NBD_MAJOR, "nbd");
	kfree(nbd_dev);
	printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
}

module_init(nbd_init);
module_exit(nbd_cleanup);

MODULE_DESCRIPTION("Network Block Device");
MODULE_LICENSE("GPL");

module_param(nbds_max, int, 0444);
MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
module_param(max_part, int, 0444);
MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
#ifndef NDEBUG
module_param(debugflags, int, 0644);
MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
#endif


text:
package org.apache.nifi.authorization;

import java.util.Collections;
import java.util.Map;

/**
 *
 */
public class StandardAuthorityProviderConfigurationContext implements AuthorityProviderConfigurationContext {

    private final String identifier;
    private final Map<String, String> properties;

    public StandardAuthorityProviderConfigurationContext(String identifier, Map<String, String> properties) {
        this.identifier = identifier;
        this.properties = properties;
    }

    @Override
    public String getIdentifier() {
        return identifier;
    }

    @Override
    public Map<String, String> getProperties() {
        return Collections.unmodifiableMap(properties);
    }

    @Override
    public String getProperty(String property) {
        return properties.get(property);
    }

}

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Index of new symbols in 2.10</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
<link rel="home" href="index.html" title="GDK-PixBuf Reference Manual">
<link rel="up" href="index.html" title="GDK-PixBuf Reference Manual">
<link rel="prev" href="api-index-2-8.html" title="Index of new symbols in 2.8">
<link rel="next" href="api-index-2-12.html" title="Index of new symbols in 2.12">
<meta name="generator" content="GTK-Doc V1.15 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">

GDK-PixBuf Reference Manual

Index of new symbols in 2.10

          Generated by GTK-Doc V1.15


text:
package br.unicamp.ic.sed.mobilemedia.media_photo;

import br.unicamp.ic.sed.mobilemedia.photo.spec.req.IMedia;

public class IAdapterMediaPhoto implements IMedia {

	IManager manager = ComponentFactory.createInstance();

	public void showLastMediaList() {

		br.unicamp.ic.sed.mobilemedia.media.spec.prov.IMedia media =
			(br.unicamp.ic.sed.mobilemedia.media.spec.prov.IMedia)
				manager.getRequiredInterface("IMedia");

		media.showLastMediaList();
	}

	public void initCopyMediaToAlbum(String oldMediaName, String oldAlbumName,
			byte[] mediaBytes, Object media, String mediaType,
			String fileExtension) {
		br.unicamp.ic.sed.mobilemedia.media.spec.prov.IMedia imedia =
			(br.unicamp.ic.sed.mobilemedia.media.spec.prov.IMedia)
				manager.getRequiredInterface("IMedia");

		imedia.initCopyMediaToAlbum(oldMediaName, oldAlbumName, mediaBytes, media, mediaType, fileExtension);

	}
}
//#endif


text:
package com.github.ibescodfnl.testmod.help;

import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.item.Item;

public class RegisterHelper {
	public static void registerBlock(Block block) {
		GameRegistry.registerBlock(block, Reference.MODID + block.getUnlocalizedName().substring(5));
	}

	public static void registerItem(Item item) {
		GameRegistry.registerItem(item, Reference.MODID + item.getUnlocalizedName().substring(5));
	}
}


text:
package org.artificer.common.visitors;

import java.lang.reflect.Method;

import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType;
import org.artificer.common.i18n.Messages;

/**
 * Helper class used to visit S-RAMP artifacts.  This should be replaced by "accept" methods implemented
 * on each of the generated S-RAMP artifact classes.  I think there might be a jax-b plugin that will do
 * that, but I haven't checked into yet.  Ex: accept(ArtifactVisitor visitor) { visitor.visit(this); }
 *
 * @author eric.wittmann@redhat.com
 */
public final class ArtifactVisitorHelper {

	/**
	 * Called to help the given visitor visit the provided artifact.
	 * @param visitor
	 * @param artifact
	 */
	public static void visitArtifact(ArtifactVisitor visitor, BaseArtifactType artifact) {
		try {
			Method method = visitor.getClass().getMethod("visit", artifact.getClass());
			method.invoke(visitor, artifact);
		} catch (Exception e) {
			// This shouldn't happen unless we've programmed something wrong in the visitor interface.
			throw new RuntimeException(
			        Messages.i18n.format("VISIT_METHOD_NOT_FOUND", visitor.getClass(), artifact.getClass()),
					e);
		}
	}

}


text:
<?php defined('BX_DOL') or die('hack attempt');

class BxBaseModTextConfig extends BxBaseModGeneralConfig
{
    protected $_aHtmlIds;

    /**
     * Determine whether Timeline post will use common content (header image + text)
     * or content received from attachments (header image + text + images + videos + polls).
     * By default the first variant is used.
     * Note. The variable can be removed in future, when all Text Based modules
     * implement 'attachments' related parameters.
     */
    protected $_bAttachmentsInTimeline;

    function __construct($aModule)
    {
        parent::__construct($aModule);

        $this->CNF = array(
            // database tables
            'TABLE_POLLS' => $aModule['db_prefix'] . 'polls',
            'TABLE_POLLS_ANSWERS' => $aModule['db_prefix'] . 'polls_answers',
            'TABLE_POLLS_ANSWERS_VOTES' => $aModule['db_prefix'] . 'polls_answers_votes',
            'TABLE_POLLS_ANSWERS_VOTES_TRACK' => $aModule['db_prefix'] . 'polls_answers_votes_track',

            // database fields
            'FIELD_POLL_ID' => 'id',
            'FIELD_POLL_AUTHOR_ID' => 'author_id',
            'FIELD_POLL_CONTENT_ID' => 'content_id',
            'FIELD_POLL_TEXT' => 'text',
            'FIELD_POLL_ANSWERS' => 'answers',

            // some params
            'PARAM_POLL_ENABLED' => true,
            'PARAM_POLL_HIDDEN_RESULTS' => false,
            'PARAM_POLL_ANONYMOUS_VOTING' => true,

            // objects
            'OBJECT_VOTES_POLL_ANSWERS' => $this->_sName . '_poll_answers',
        );

        $this->_aJsClasses = array(
            'poll' => $this->_sClassPrefix . 'Polls'
        );

        $this->_aJsObjects = array(
            'poll' => 'o' . $this->_sClassPrefix . 'Polls'
        );

        $sPrefix = str_replace('_', '-', $this->_sName);
        $this->_aHtmlIds = array(
            'add_poll_popup' =>  $sPrefix . '-add-poll-popup',
            'add_poll_form_field' => $sPrefix . '-add-poll-form-field',
            'polls_showcase' => $sPrefix . '-polls-showcase-',
            'poll' => $sPrefix . '-poll-',
            'poll_content' => $sPrefix . '-poll-content-',
            'poll_view_menu' => $sPrefix . '-poll-view-menu',
            'poll_view_link_answers' => $sPrefix . '-poll-view-answers-',
            'poll_view_link_results' => $sPrefix . '-poll-view-results-',
        );

        $this->_bAttachmentsInTimeline = false;
    }

    public function isAttachmentsInTimeline()
    {
        return $this->_bAttachmentsInTimeline;
    }

    public function getHtmlIds($sKey = '')
    {
        if(empty($sKey))
            return $this->_aHtmlIds;

        return isset($this->_aHtmlIds[$sKey]) ? $this->_aHtmlIds[$sKey] : '';
    }
}

/** @} */


text:
/* -*-C++-*-
*****************************************************************************
*
* File:         ex_sscp_main.cpp
* Description:  This is the main program for SSCP. SQL stats control process The process
*				does the following:
*				- Creates the shared segment
*               . Handle messages from SSMP
*
* Created:      04/17/2006
* Language:     C++
*
*****************************************************************************
*/
#include "Platform.h"
#ifdef _DEBUG
#include <fstream>
#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include <errno.h>
#include "ExCextdecs.h"
#include "ex_ex.h"
#include "Ipc.h"
#include "Globals.h"
#include "SqlStats.h"
#include "memorymonitor.h"
#include "sscpipc.h"
#include "rts_msg.h"
#include "ex_stdh.h"
#include "ExStats.h"
#include "PortProcessCalls.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include "seabed/ms.h"
#include "seabed/fs.h"
extern void my_mpi_fclose();
#include "SCMVersHelp.h"
DEFINE_DOVERS(mxsscp)
void  runServer(Int32 argc, char **argv);

Int32 main(Int32 argc, char **argv)
{
  dovers(argc, argv);
  msg_debug_hook("mxsscp", "mxsscp.hook");
  try {
    file_init_attach(&argc, &argv, TRUE, (char *)"");
  }
  catch (SB_Fatal_Excep &e) {
    SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, e.what(), 0);
    exit(1);
  }

  try {
    file_mon_process_startup(true);
  }
  catch (SB_Fatal_Excep &e) {
    SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, e.what(), 0);
    exit(1);
  }

  atexit(my_mpi_fclose);
  // setup log4cxx, need to be done here so initLog4cxx can have access to
  // process information since it is needed to compose the log name
  // the log4cxx log name for this ssmp process  will be
  // based on this process' node number sscp_<nid>.log
  QRLogger::instance().setModule(QRLogger::QRL_SSCP);
  QRLogger::instance().initLog4cxx("log4cxx.trafodion.sscp.config");

  // Synchronize C and C++ output streams
  ios::sync_with_stdio();

#ifdef _DEBUG
  // Redirect stdout and stderr to files named in environment
  // variables
  const char *stdOutFile = getenv("SQ_SSCP_STDOUT");
  const char *stdErrFile = getenv("SQ_SSCP_STDERR");
  Int32 fdOut = -1;
  Int32 fdErr = -1;

  if (stdOutFile && stdOutFile[0])
  {
    fdOut = open(stdOutFile,
                 O_WRONLY | O_APPEND | O_CREAT | O_SYNC,
                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fdOut >= 0)
    {
      fprintf(stderr, "[Redirecting MXSSCP stdout to %s]\n", stdOutFile);
      fflush(stderr);
      dup2(fdOut, fileno(stdout));
    }
    else
    {
      fprintf(stderr, "*** WARNING: could not open %s for redirection: %s.\n",
              stdOutFile, strerror(errno));
    }
  }

  if (stdErrFile && stdErrFile[0])
  {
    fdErr = open(stdErrFile,
                 O_WRONLY | O_APPEND | O_CREAT | O_SYNC,
                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fdErr >= 0)
    {
      fprintf(stderr, "[Redirecting MXUDR stderr to %s]\n", stdErrFile);
      fflush(stderr);
      dup2(fdErr, fileno(stderr));
    }
    else
    {
      fprintf(stderr, "*** WARNING: could not open %s for redirection: %s.\n",
              stdErrFile, strerror(errno));
    }
  }
  runServer(argc, argv);

  if (fdOut >= 0)
  {
    close(fdOut);
  }
  if (fdErr >= 0)
  {
    close(fdErr);
  }
#else
  runServer(argc, argv);
#endif
  return 0;
}
void runServer(Int32 argc, char **argv)
{
  Int32 shmid;
  jmp_buf sscpJmpBuf;
  StatsGlobals *statsGlobals = NULL;
  void *statsGlobalsAddr;
  NABoolean createStatsGlobals = FALSE;
  CliGlobals *cliGlobals = CliGlobals::createCliGlobals(FALSE);
  char tmbuf[64];
  time_t now;
  struct tm *nowtm;

  long maxSegSize = STATS_MAX_SEG_SIZE;
  char *envSegSize = getenv("MX_RTS_STATS_SEG_SIZE");
  if (envSegSize)
  {
    maxSegSize = (long) str_atoi(envSegSize, str_len(envSegSize));
    if (maxSegSize < 32)
      maxSegSize = 32;
    else if (maxSegSize > 256)
      maxSegSize = 256;
    maxSegSize *= 1024 * 1024;
  }
  long enableHugePages = 0;
  int shmFlag = RMS_SHMFLAGS;
  char *envShmHugePages = getenv("SQ_RMS_ENABLE_HUGEPAGES");
  if (envShmHugePages != NULL)
  {
     enableHugePages = (long) str_atoi(envShmHugePages,
                         str_len(envShmHugePages));
     if (enableHugePages > 0)
       shmFlag =  shmFlag | SHM_HUGETLB;
  }

  now = time(NULL);
  nowtm = localtime(&now);
  strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S ", nowtm);

  if ((shmid = shmget((key_t)getStatsSegmentId(),
                         0,  // size doesn't matter unless we are creating.
                         shmFlag)) == -1)
  {
    if (errno == ENOENT)
    {
      // Normal case, segment does not exist yet. Try to create.
      bool didCreate = true;
      if ((shmid = shmget((key_t)getStatsSegmentId(),
                                maxSegSize,
                                shmFlag | IPC_CREAT)) == -1)
      {
        if (enableHugePages > 0)
        {
          enableHugePages = 0;
          // try again withouf hugepages
          shmFlag =  shmFlag & ~SHM_HUGETLB;
          if ((shmid = shmget((key_t)getStatsSegmentId(),
                                    maxSegSize,
                                    shmFlag | IPC_CREAT)) == -1)
            didCreate = false;
        }
        else
          didCreate = false;
      }

      if (didCreate)
      {
        cout << tmbuf
             << " RMS Shared segment id = "
             << shmid << ", key = "
             << (key_t)getStatsSegmentId() ;
        if (enableHugePages > 0)
          cout << ", created with huge pages support." << endl;
        else
          cout << ", created without huge pages support." << endl;

        createStatsGlobals = TRUE;
      }
      else
      {
        cout << tmbuf
             << " Shmget failed, key = "
             << getStatsSegmentId()
             <<", Error code: "
             << errno
             << " ("
             << strerror(errno)
             << ")" << endl;
        exit(errno);
      }
    } // if ENOENT (i.e., attempting creation.)
  }
  else
  {
     cout << tmbuf << " RMS Shared segment exists, attaching to it, shmid="<< shmid << ", key=" << (key_t)getStatsSegmentId() << "\n";
  }
  if ((statsGlobalsAddr = shmat(shmid, getRmsSharedMemoryAddr(), 0))
		== (void *)-1)
  {
    cout << tmbuf << "Shmat failed, shmid=" <<shmid << ", key=" << (key_t) getStatsSegmentId() << ", Error code : "  << errno << "(" << strerror(errno) << ")\n";
    exit(errno);
  }
  char *statsGlobalsStartAddr = (char *)statsGlobalsAddr;
  if (createStatsGlobals)
  {
     short envType = StatsGlobals::RTS_GLOBAL_ENV;
     statsGlobals = new (statsGlobalsStartAddr)
             StatsGlobals((void *)statsGlobalsAddr, envType, maxSegSize);
     cliGlobals->setSharedMemId(shmid);
     // We really should not squirrel the statsGlobals pointer away like
     // this until the StatsGloblas is initialized, but
     // statsGlobals->init() needs it ......
     cliGlobals->setStatsGlobals(statsGlobals);
     statsGlobals->init();
  }
  else
  {
    statsGlobals = (StatsGlobals *)statsGlobalsAddr;
    cliGlobals->setSharedMemId(shmid);
    cliGlobals->setStatsGlobals(statsGlobals);
  }
  XPROCESSHANDLE_GETMINE_(statsGlobals->getSscpProcHandle());
  NAHeap *sscpHeap = cliGlobals->getExecutorMemory();
  cliGlobals->setJmpBufPtr(&sscpJmpBuf);
  if (setjmp(sscpJmpBuf))
    NAExit(1); // Abend
  IpcEnvironment  *sscpIpcEnv = new (sscpHeap) IpcEnvironment(sscpHeap, cliGlobals->getEventConsumed(),
      FALSE, IPC_SQLSSCP_SERVER, FALSE, TRUE);

  SscpGlobals *sscpGlobals = NULL;

  sscpGlobals = new (sscpHeap) SscpGlobals(sscpHeap, statsGlobals);

  // Currently open $RECEIVE with 256
  SscpGuaReceiveControlConnection *cc =
	 new(sscpHeap) SscpGuaReceiveControlConnection(sscpIpcEnv,
					  sscpGlobals,
                                           256);
  sscpIpcEnv->setControlConnection(cc);
  while (TRUE)
  {
     while (cc->getConnection() == NULL)
      cc->wait(IpcInfiniteTimeout);

#ifdef _DEBUG_RTS
    cerr << "No. of Requesters-1 "  << cc->getNumRequestors() << " \n";
#endif
    while (cc->getNumRequestors() > 0)
    {
      sscpIpcEnv->getAllConnections()->waitOnAll(IpcInfiniteTimeout);
    } // Inner while
  }
}  // runServer


text:
if [ -z $1 ]; then
    bin/phpunit --bootstrap vendor/autoload.php tests/ --verbose --colors=always --debug
else
    bin/phpunit --bootstrap vendor/autoload.php tests/ --verbose --colors=always --group=$1 --debug
fi


text:
Deploying sample to GitHub Pages (gh-pages branch):

1. Generate SSH keys for passwordless pushing to github (see https://help.github.com/articles/generating-ssh-keys/ )
2. Run grunt deploy_samples - This will build the samples web app and deploy it to github pages:
3. Run samples app at: http://chromium.github.io/axiom/samples/web_shell/index.html


text:
CDC Training Information System

Sign In

                 <?php $this->load->section('form', 'sessions/form')?>
                 <?php echo $this->load->get_section('form') ?>

CDC Training Information System

Registration

                 <?php $this->load->section('register_form', 'registration/form', array('registrant' => isset($registrant) ? $registrant : new User )) ?>
                 <?= $this->load->get_section('register_form') ?>


text:
import {Component} from 'angular2/core';

let template = require('./navbar.html');

@Component({
  selector: 'navbar',
  template: template
})

/**
 * @class Navbar
 * @description Navbar Component
 * @param Component Template injected
 * @returns exports component
 */
export class Navbar {
  images: Object;
  constructor() {
    this.images = {
    };
  }
}


text:
.. _database:

Database
==========
Roboragi uses caching to make search results faster and more accurate.

Build in database support
--------------------------
Roboragi comes with built in support for SQLite3 and PostgreSQL databases.

To use the built in SQLite3 support, simply use the ``from_sqlite`` method as
such:

.. code-block:: python3

    from roboragi import Roboragi

    async def main():
        mal_config = {
            'user': 'MAL User name',
            'password': 'MAL password'
        }
        anilist_config = {
            'id': 'Anilist client id',
            'secret': 'Anilist client secret'
        }

        db_path = 'path/to/database'

        robo = await Roboragi.from_sqlite(
            mal_config, anilist_config, db_path
        )

To use the built in PostgreSQL support, you will need
`asyncpg <https://github.com/MagicStack/asyncpg>`_ to be installed. Check
:ref:`install` for more information.
Then, use the ``from_postgres`` method as such:

.. code-block:: python3

    from roboragi import Roboragi

    async def main():
        mal_config = {
            'user': 'MAL User name',
            'password': 'MAL password'
        }
        anilist_config = {
            'id': 'Anilist client id',
            'secret': 'Anilist client secret'
        }
        db_config = {
            "host": "localhost",
            "port": "5432",
            "user": "postgres",
            "database": "postgres"
        }

        robo = await Roboragi.from_postgres(
            mal_config, anilist_config, db_config, schema='my_schema'
        )

.. _Extending DatabaseController:

Extending DatabaseController
----------------------------------------------
You may also write your custom implementation of the database controller if you
wish. To get started, inherit from the ``DataController`` class as such:

.. code-block:: python3

    from roboragi import DataController

    class MyDatabase(DataController):
        def __init__(self, logger):
            super().__init__(logger)

You will need to initialize the super class with a logger object.

Next, you will need to implement ALL of the following methods. The methods
MUST be defined with ``async def``.

.. code-block:: python3

    @abstractmethod
    async def get_identifier(self, query: str,
                             medium: Medium) -> Optional[Dict[Site, str]]:
        """
        Get the identifier of a given search query.

        :param query: the search query.
        :type query: str

        :param medium: the medium type.
        :type medium: Medium

        :return:
            A dict of all identifiers for this search query for all sites,
            None if nothing is found.
        :rtype: Optional[Dict[Site, str]]
        """
        raise NotImplementedError

    @abstractmethod
    async def set_identifier(self, name: str, medium: Medium,
                             site: Site, identifier: str):
        """
        Set the identifier for a given name.

        :param name: the name.
        :type name: str

        :param medium: the medium type.
        :type medium: Medium

        :param site: the site.
        :type site: Site

        :param identifier: the identifier.
        :type identifier: str
        """
        raise NotImplementedError

    @abstractmethod
    async def get_mal_title(self, id_: str, medium: Medium) -> Optional[str]:
        """
        Get a MAL title by its id.

        :param id_: th MAL id.
        :type id_: str

        :param medium: the medium type.
        :type medium: Medium

        :return: The MAL title if it's found.
        :rtype: Optional[str]
        """
        raise NotImplementedError

    @abstractmethod
    async def set_mal_title(self, id_: str, medium: Medium, title: str):
        """
        Set the MAL title for a given id.

        :param id_: the MAL id.
        :type id_: str

        :param medium: The medium type.
        :type medium: Medium

        :param title: The MAL title for the given id.
        :type title: str
        """
        raise NotImplementedError

    @abstractmethod
    async def medium_data_by_id(self, id_: str, medium: Medium,
                                site: Site) -> Optional[dict]:
        """
        Get data by id.

        :param id_: the id.
        :type id_: str

        :param medium: the medium type.
        :type medium: Medium

        :param site: the site.
        :type site: Site

        :return: the data for that id if found.
        :rtype: Optional[dict]
        """
        raise NotImplementedError

    @abstractmethod
    async def set_medium_data(self, id_: str, medium: Medium,
                              site: Site, data: dict):
        """
        Set the data for a given id.

        :param id_: the id.
        :type id_: str

        :param medium: the medium type.
        :type medium: Medium

        :param site: the site.
        :type site: Site

        :param data: the data for the id.
        :type data: dict
        """
        raise NotImplementedError


text:
package hudson.ivy;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Launcher;
import hudson.Util;
import hudson.ivy.IvyBuild.ProxyImpl2;
import hudson.ivy.builder.IvyBuilderType;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.DependencyGraph;
import hudson.model.Environment;
import hudson.model.Fingerprint;
import hudson.model.Hudson;
import hudson.model.ParametersAction;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.Cause.UpstreamCause;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.scm.ChangeLogSet;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Publisher;
import hudson.util.StreamTaskListener;

import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.apache.ivy.Ivy;
import org.apache.ivy.Ivy.IvyCallback;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.core.sort.SortOptions;
import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
import org.apache.ivy.util.Message;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.types.FileSet;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

/**
 * {@link Build} for {@link IvyModuleSet}.
 *
 *

 * A "build" of {@link IvyModuleSet} consists of:
 *
 *

 *
Update the workspace.
 *
Parse ivy.xml files
 *
Trigger module builds.
 *

 *
 * This object remembers the changelog and what {@link IvyBuild}s are done on
 * this.
 *
 * @author Timothy Bingaman
 */
public class IvyModuleSetBuild extends AbstractIvyBuild<IvyModuleSet, IvyModuleSetBuild> {
    /**
     * {@link IvyReporter}s that will contribute project actions. Can be null if
     * there's none.
     */
    /* package */List<IvyReporter> projectActionReporters;

    public IvyModuleSetBuild(IvyModuleSet job) throws IOException {
        super(job);
    }

    public IvyModuleSetBuild(IvyModuleSet project, File buildDir) throws IOException {
        super(project, buildDir);
    }

    /**
     * Exposes {@code ANT_OPTS} to forked processes.
     *
     * When we fork Ant, we do so directly by executing Java, thus this
     * environment variable is pointless (we have to tweak JVM launch option
     * correctly instead, which can be seen in {@link IvyProcessFactory}), but
     * setting the environment variable explicitly is still useful in case this
     * Ant forks other Ant processes via normal way. See HUDSON-3644.
     */
    @Override
    public EnvVars getEnvironment(TaskListener log) throws IOException, InterruptedException {
        EnvVars envs = super.getEnvironment(log);
        envs.putAll(project.getIvyBuilderType().getEnvironment());
        return envs;
    }

    /**
     * Displays the combined status of all modules.
     *

     * More precisely, this picks up the status of this build itself, plus all
     * the latest builds of the modules that belongs to this build.
     */
    @Override
    public Result getResult() {
        Result r = super.getResult();

        for (IvyBuild b : getModuleLastBuilds().values()) {
            Result br = b.getResult();
            if (r == null)
                r = br;
            else if (br == Result.NOT_BUILT)
                continue; // UGLY: when computing combined status, ignore the
            // modules that were not built
            else if (br != null)
                r = r.combine(br);
        }

        return r;
    }

    /**
     * Returns the filtered changeset entries that match the given module.
     */
    /* package */List<ChangeLogSet.Entry> getChangeSetFor(final IvyModule mod) {
        return new ArrayList<ChangeLogSet.Entry>() {
            {
                for (ChangeLogSet.Entry e : getChangeSet()) {
                    if (isDescendantOf(e, mod)) {
                        add(e);
                    }
                }
            }

            /**
             * Does this change happen somewhere in the given module or its
             * descendants?
             */
            private boolean isDescendantOf(ChangeLogSet.Entry e, IvyModule mod) {
                for (String path : e.getAffectedPaths())
                    if (path.startsWith(mod.getRelativePathToModuleRoot()))
                        return true;
                return false;
            }
        };
    }

    /**
     * Computes the module builds that correspond to this build.
     *

     * A module may be built multiple times (by the user action), so the value
     * is a list.
     */
    public Map<IvyModule, List<IvyBuild>> getModuleBuilds() {
        Collection<IvyModule> mods = getParent().getModules();

        // identify the build number range. [start,end)
        IvyModuleSetBuild nb = getNextBuild();
        int end = nb != null ? nb.getNumber() : Integer.MAX_VALUE;

        // preserve the order by using LinkedHashMap
        Map<IvyModule, List<IvyBuild>> r = new LinkedHashMap<IvyModule, List<IvyBuild>>(mods.size());

        for (IvyModule m : mods) {
            List<IvyBuild> builds = new ArrayList<IvyBuild>();
            IvyBuild b = m.getNearestBuild(number);
            while (b != null && b.getNumber() < end) {
                builds.add(b);
                b = b.getNextBuild();
            }
            r.put(m, builds);
        }

        return r;
    }

    @Override
    public Object getDynamic(String token, StaplerRequest req, StaplerResponse rsp) {
        // map corresponding module build under this object
        if (token.indexOf('$') > 0) {
            IvyModule m = getProject().getModule(token);
            if (m != null)
                return m.getBuildByNumber(getNumber());
        }
        return super.getDynamic(token, req, rsp);
    }

    /**
     * Computes the latest module builds that correspond to this build.
     */
    public Map<IvyModule, IvyBuild> getModuleLastBuilds() {
        Collection<IvyModule> mods = getParent().getModules();

        // identify the build number range. [start,end)
        IvyModuleSetBuild nb = getNextBuild();
        int end = nb != null ? nb.getNumber() : Integer.MAX_VALUE;

        // preserve the order by using LinkedHashMap
        Map<IvyModule, IvyBuild> r = new LinkedHashMap<IvyModule, IvyBuild>(mods.size());

        for (IvyModule m : mods) {
            IvyBuild b = m.getNearestOldBuild(end - 1);
            if (b != null && b.getNumber() >= getNumber())
                r.put(m, b);
        }

        return r;
    }

    public void registerAsProjectAction(IvyReporter reporter) {
        if (projectActionReporters == null)
            projectActionReporters = new ArrayList<IvyReporter>();
        projectActionReporters.add(reporter);
    }

    /**
     * Finds {@link Action}s from all the module builds that belong to this
     * {@link IvyModuleSetBuild}. One action per one {@link IvyModule}, and
     * newer ones take precedence over older ones.
     */
    public <T extends Action> List<T> findModuleBuildActions(Class<T> action) {
        Collection<IvyModule> mods = getParent().getModules();
        List<T> r = new ArrayList<T>(mods.size());

        // identify the build number range. [start,end)
        IvyModuleSetBuild nb = getNextBuild();
        int end = nb != null ? nb.getNumber() - 1 : Integer.MAX_VALUE;

        for (IvyModule m : mods) {
            IvyBuild b = m.getNearestOldBuild(end);
            while (b != null && b.getNumber() >= number) {
                T a = b.getAction(action);
                if (a != null) {
                    r.add(a);
                    break;
                }
                b = b.getPreviousBuild();
            }
        }

        return r;
    }

    @Override
    public void run() {
        run(new RunnerImpl());
        getProject().updateTransientActions();
    }

    @Override
    public Fingerprint.RangeSet getDownstreamRelationship(AbstractProject that) {
        Fingerprint.RangeSet rs = super.getDownstreamRelationship(that);
        for (List<IvyBuild> builds : getModuleBuilds().values())
            for (IvyBuild b : builds)
                rs.add(b.getDownstreamRelationship(that));
        return rs;
    }

    /**
     * Called when a module build that corresponds to this module set build has
     * completed.
     */
    /* package */void notifyModuleBuild(IvyBuild newBuild) {
        try {
            // update module set build number
            getParent().updateNextBuildNumber();

            // update actions
            Map<IvyModule, List<IvyBuild>> moduleBuilds = getModuleBuilds();

            // actions need to be replaced atomically especially
            // given that two builds might complete simultaneously.
            synchronized (this) {
                boolean modified = false;

                List<Action> actions = getActions();
                Set<Class<? extends AggregatableAction>> individuals = new HashSet<Class<? extends AggregatableAction>>();
                for (Action a : actions) {
                    if (a instanceof IvyAggregatedReport) {
                        IvyAggregatedReport mar = (IvyAggregatedReport) a;
                        mar.update(moduleBuilds, newBuild);
                        individuals.add(mar.getIndividualActionType());
                        modified = true;
                    }
                }

                // see if the new build has any new aggregatable action that we
                // haven't seen.
                for (AggregatableAction aa : newBuild.getActions(AggregatableAction.class)) {
                    if (individuals.add(aa.getClass())) {
                        // new AggregatableAction
                        IvyAggregatedReport mar = aa.createAggregatedAction(this, moduleBuilds);
                        mar.update(moduleBuilds, newBuild);
                        actions.add(mar);
                        modified = true;
                    }
                }

                if (modified) {
                    save();
                    getProject().updateTransientActions();
                }
            }

            // symlink to this module build
            String moduleFsName = newBuild.getProject().getModuleName().toFileSystemName();
            Util.createSymlink(getRootDir(),
                    "../../modules/" + moduleFsName + "/builds/" + newBuild.getId() /*ugly!*/,
                    moduleFsName, StreamTaskListener.NULL);
        } catch (IOException e) {
            LOGGER.log(Level.WARNING, "Failed to update " + this, e);
        } catch (InterruptedException e) {
            LOGGER.log(Level.WARNING, "Failed to update " + this, e);
        }
    }

    /**
     * The sole job of the {@link IvyModuleSet} build is to update SCM and
     * triggers module builds.
     */
    private class RunnerImpl extends AbstractRunner {
        private Map<ModuleName,IvyBuild.ProxyImpl2> proxies;

        @Override
        protected Result doRun(final BuildListener listener) throws Exception {
            PrintStream logger = listener.getLogger();
            try {
                EnvVars envVars = getEnvironment(listener);

                parseIvyDescriptorFiles(listener, logger, envVars);

                if (!project.isAggregatorStyleBuild()) {
                    // start module builds
                    DependencyGraph graph = Hudson.getInstance().getDependencyGraph();
                    Set<IvyModule> triggeredModules = new HashSet<IvyModule>();
                    if (!project.isIncrementalBuild() || IvyModuleSetBuild.this.getChangeSet().isEmptySet()) {
                        for (IvyModule module : project.sortedActiveModules) {
                            // Don't trigger builds if we've already triggered
                            // one
                            // of their dependencies.
                            // It's safe to just get the direct dependencies
                            // since
                            // the modules are sorted in dependency order.
                            List<AbstractProject> ups = module.getUpstreamProjects();
                            boolean triggerBuild = true;
                            for (AbstractProject upstreamDep : ups) {
                                if (triggeredModules.contains(upstreamDep)) {
                                    triggerBuild = false;
                                    break;
                                }
                            }

                            if (triggerBuild) {
                                logger.println("Triggering " + module.getModuleName());
                                module.scheduleBuild(new ParameterizedUpstreamCause(((Run<?, ?>) IvyModuleSetBuild.this), IvyModuleSetBuild.this.getActions(ParametersAction.class)));
                            }
                            triggeredModules.add(module);
                        }
                    } else {
                        for (IvyModule module : project.sortedActiveModules) {
                            // If there are changes for this module, add it.
                            // Also add it if we've never seen this module
                            // before,
                            // or if the previous build of this module
                            // failed or was unstable.
                            boolean triggerBuild = false;
                            if ((module.getLastBuild() == null) || (!getChangeSetFor(module).isEmpty())
                                    || (module.getLastBuild().getResult().isWorseThan(Result.SUCCESS))) {
                                triggerBuild = true;
                                List<AbstractProject> ups = module.getUpstreamProjects();
                                for (AbstractProject upstreamDep : ups) {
                                    if (triggeredModules.contains(upstreamDep)) {
                                        triggerBuild = false;
                                        triggeredModules.add(module);
                                        break;
                                    }
                                }
                            }

                            if (triggerBuild) {
                                logger.println("Triggering " + module.getModuleName());
                                module.scheduleBuild(new ParameterizedUpstreamCause(((Run<?, ?>) IvyModuleSetBuild.this), IvyModuleSetBuild.this.getActions(ParametersAction.class)));
                                triggeredModules.add(module);
                            }
                        }
                    }
                } else {
                    // do builds here
                    try {
                        List<BuildWrapper> wrappers = new ArrayList<BuildWrapper>();
                        for (BuildWrapper w : project.getBuildWrappersList())
                            wrappers.add(w);
                        ParametersAction parameters = getAction(ParametersAction.class);
                        if (parameters != null)
                            parameters.createBuildWrappers(IvyModuleSetBuild.this, wrappers);

                        for (BuildWrapper w : wrappers) {
                            Environment e = w.setUp(IvyModuleSetBuild.this, launcher, listener);
                            if (e == null)
                                return Result.FAILURE;
                            buildEnvironments.add(e);
                            e.buildEnvVars(envVars); // #3502: too late for
                            // getEnvironment to do
                            // this
                        }

                        if (!preBuild(listener, project.getPublishers()))
                            return Result.FAILURE;

                        List<String> changedModules = new ArrayList<String>();
                        for (IvyModule m : project.sortedActiveModules) {
                            // Check if incrementalBuild is selected and that
                            // there are changes -
                            // we act as if incrementalBuild is not set if there
                            // are no changes.
                            if (!IvyModuleSetBuild.this.getChangeSet().isEmptySet() && project.isIncrementalBuild()) {
                                // If there are changes for this module, add it.
                                if (!getChangeSetFor(m).isEmpty()) {
                                    changedModules.add(m.getModuleName().name);
                                }
                            }
                        }

                        Properties additionalProperties = null;
                        if (project.isAggregatorStyleBuild() && project.isIncrementalBuild()) {
                            additionalProperties = new Properties();
                            additionalProperties.put(project.getChangedModulesProperty() == null ? "hudson.ivy.changedModules" : project
                                    .getChangedModulesProperty(), StringUtils.join(changedModules, ','));
                        }

                        IvyBuilderType ivyBuilderType = project.getIvyBuilderType();
                        hudson.tasks.Builder builder = ivyBuilderType.getBuilder(additionalProperties, null, buildEnvironments);
                        logger.println("Building project with " + ivyBuilderType.getDescriptor().getDisplayName());

                        if (builder.perform(IvyModuleSetBuild.this, launcher, listener))
                            return Result.SUCCESS;

                        return Result.FAILURE;
                    } finally {
                        // tear down in reverse order
                        boolean failed = false;
                        for (int i = buildEnvironments.size() - 1; i >= 0; i--) {
                            if (!buildEnvironments.get(i).tearDown(IvyModuleSetBuild.this, listener)) {
                                failed = true;
                            }
                        }
                        buildEnvironments = null;
                        // WARNING The return in the finally clause will trump
                        // any return before
                        if (failed)
                            return Result.FAILURE;
                    }
                }

                return null;
            } catch (AbortException e) {
                if (e.getMessage() != null)
                    listener.error(e.getMessage());
                return Result.FAILURE;
            } catch (InterruptedIOException e) {
                e.printStackTrace(listener.error("Aborted Ivy execution for InterruptedIOException"));
                return Result.ABORTED;
            } catch (InterruptedException e) {
                e.printStackTrace(listener.error("Aborted Ivy execution for InterruptedException"));
                return Result.ABORTED;
            } catch (IOException e) {
                e.printStackTrace(listener.error(Messages.IvyModuleSetBuild_FailedToParseIvyXml()));
                return Result.FAILURE;
            } catch (RunnerAbortedException e) {
                return Result.FAILURE;
            } catch (RuntimeException e) {
                // bug in the code.
                e.printStackTrace(listener.error("Processing failed due to a bug in the code. Please report this to users@hudson.dev.java.net"));
                logger.println("project=" + project);
                logger.println("project.getModules()=" + project.getModules());
                throw e;
            }
        }

        private void parseIvyDescriptorFiles(BuildListener listener, PrintStream logger, EnvVars envVars) throws IOException, InterruptedException {
            logger.println("Parsing Ivy Descriptor Files");

            List<IvyModuleInfo> ivyDescriptors;
            try {
            	IvyXmlParser parser = new IvyXmlParser(listener, project, getModuleRoot().getRemote());
            	if (getModuleRoot().getChannel() instanceof Channel)
            		((Channel) getModuleRoot().getChannel()).preloadJar(parser, Ivy.class);
                ivyDescriptors = getModuleRoot().act(parser);
            } catch (IOException e) {
                if (e.getCause() instanceof AbortException)
                    throw (AbortException) e.getCause();
                throw e;
            } catch (Throwable e) {
				throw new IOException("Unable to parse ivy descriptors", e);
			}

            // update the module list
            Map<ModuleName, IvyModule> modules = project.modules;
            synchronized (modules) {
                Map<ModuleName, IvyModule> old = new HashMap<ModuleName, IvyModule>(modules);
                List<IvyModule> sortedModules = new ArrayList<IvyModule>();

                modules.clear();
                for (IvyModuleInfo ivyDescriptor : ivyDescriptors) {
                    IvyModule mm = old.get(ivyDescriptor.name);
                    if (mm != null) {// found an existing matching module
                        if (debug)
                            logger.println("Reconfiguring " + mm);
                        mm.reconfigure(ivyDescriptor);
                        modules.put(ivyDescriptor.name, mm);
                    } else {// this looks like a new module
                        logger.println(Messages.IvyModuleSetBuild_DiscoveredModule(ivyDescriptor.name, ivyDescriptor.displayName));
                        mm = new IvyModule(project, ivyDescriptor, getNumber());
                        modules.put(mm.getModuleName(), mm);
                    }
                    sortedModules.add(mm);
                    mm.save();
                }

                // at this point the list contains all the live modules
                project.sortedActiveModules = sortedModules;

                // remaining modules are no longer active.
                old.keySet().removeAll(modules.keySet());
                for (IvyModule om : old.values()) {
                    if (debug)
                        logger.println("Disabling " + om);
                    om.makeDisabled(true);
                }
                modules.putAll(old);
            }

            // we might have added new modules
            Hudson.getInstance().rebuildDependencyGraph();

            // module builds must start with this build's number
            for (IvyModule m : modules.values())
                m.updateNextBuildNumber(getNumber());
        }

        @Override
        protected void post2(BuildListener listener) throws Exception {
            // asynchronous executions from the build might have left some
            // unsaved state,
            // so just to be safe, save them all.
            // TODO: uncomment when proxying stuff is done
//            for (IvyBuild b : getModuleLastBuilds().values())
//                b.save();

            if (project.isAggregatorStyleBuild()) {
                performAllBuildSteps(listener, project.getPublishers(), true);
            }
            performAllBuildSteps(listener, project.getProperties(), true);

            // aggregate all module fingerprints to us,
            // so that dependencies between module builds can be understood as
            // dependencies between module set builds.
            // TODO: we really want to implement this as a publisher,
            // but we don't want to ask for a user configuration, nor should it
            // show up in the persisted record.
            // IvyFingerprinter.aggregate(IvyModuleSetBuild.this);
        }

        @Override
        public void cleanUp(BuildListener listener) throws Exception {
            if (project.isAggregatorStyleBuild()) {
                // schedule downstream builds. for non aggregator style builds,
                // this is done by each module
                scheduleDownstreamBuilds(listener);
                performAllBuildSteps(listener, project.getPublishers(), false);
            }

            performAllBuildSteps(listener, project.getProperties(), false);
        }
    }

    /**
     * Runs Ant and builds the project.
     *
     * This is only used for {@link IvyModuleSet#isAggregatorStyleBuild() the
     * aggregator style build}.
     */
    private static final class Builder extends IvyBuilder {
        private final Map<ModuleName,IvyBuildProxy2> proxies;
        private final Map<ModuleName,List<Publisher>> modulePublishers = new HashMap<ModuleName,List<Publisher>>();

        private IvyBuildProxy2 lastProxy;

        /**
         * Kept so that we can finalize them in the end method.
         */
        private final transient Map<ModuleName,ProxyImpl2> sourceProxies;

        public Builder(BuildListener listener,Map<ModuleName,ProxyImpl2> proxies, Collection<IvyModule> modules, List<String> goals, Map<String,String> systemProps) {
            super(listener,goals,systemProps);
            this.sourceProxies = proxies;
            this.proxies = new HashMap<ModuleName, IvyBuildProxy2>(proxies);
            for (Entry<ModuleName,IvyBuildProxy2> e : this.proxies.entrySet())
                e.setValue(new FilterImpl(e.getValue()));

            for (IvyModule m : modules)
                modulePublishers.put(m.getModuleName(),m.createModulePublishers());
        }

        private class FilterImpl extends IvyBuildProxy2.Filter<IvyBuildProxy2> implements Serializable {
            public FilterImpl(IvyBuildProxy2 core) {
                super(core);
            }

            @Override
            public void executeAsync(final BuildCallable<?,?> program) throws IOException {
                futures.add(Channel.current().callAsync(new AsyncInvoker(core,program)));
            }

            private static final long serialVersionUID = 1L;
        }

        /**
         * Invoked after the Ant has finished running, and in the master, not in the Ant process.
         */
        void end(Launcher launcher) throws IOException, InterruptedException {
            for (Map.Entry<ModuleName,ProxyImpl2> e : sourceProxies.entrySet()) {
                ProxyImpl2 p = e.getValue();
                for (Publisher publisher : modulePublishers.get(e.getKey())) {
                    // we'd love to do this when the module build ends, but doing so requires
                    // we know how many task segments are in the current build.
                    publisher.perform(p.owner(),launcher,listener);
                    p.appendLastLog();
                }
                p.close();
            }
        }

        @Override
        public Result call() throws IOException {
            try {
                return super.call();
            } finally {
                if(lastProxy!=null)
                    lastProxy.appendLastLog();
            }
        }

        @Override
        void preBuild(BuildEvent event) throws IOException, InterruptedException {
            // TODO
        }

        @Override
        void postBuild(BuildEvent event) throws IOException, InterruptedException {
            // TODO
        }

        @Override
        void preModule(BuildEvent event) throws InterruptedException, IOException, AbortException {
            File baseDir = event.getProject().getBaseDir();
            // TODO: find the module that contains this path?
//            ModuleName name = new ModuleName(event.getProject().getBaseDir());
//            IvyBuildProxy2 proxy = proxies.get(name);
//            listener.getLogger().flush();   // make sure the data until here are all written
//            proxy.start();
//            for (IvyReporter r : reporters.get(name))
//                if(!r.preBuild(proxy,event,listener))
//                    throw new AbortException(r+" failed");
        }

        @Override
        void postModule(BuildEvent event) throws InterruptedException, IOException, AbortException {
//            ModuleName name = new ModuleName(project);
//            IvyBuildProxy2 proxy = proxies.get(name);
//            List<IvyReporter> rs = reporters.get(name);
//            if(rs==null) { // probe for issue #906
//                throw new AssertionError("reporters.get("+name+")==null. reporters="+reporters+" proxies="+proxies);
//            }
//            for (IvyReporter r : rs)
//                if(!r.postBuild(proxy,event,listener))
//                    throw new hudson.maven.agent.AbortException(r+" failed");
//            listener.getLogger().flush();   // make sure the data until here are all written
//            proxy.end();
//            lastProxy = proxy;
        }

        private static final long serialVersionUID = 1L;
    }

    /**
     * Used to tunnel exception from Ant through remoting.
     */
    private static final class AntExecutionException extends RuntimeException {
        private AntExecutionException(Exception cause) {
            super(cause);
        }

        @Override
        public Exception getCause() {
            return (Exception) super.getCause();
        }

        private static final long serialVersionUID = 1L;
    }

    /**
     * Executed on the slave to parse ivy.xml files and extract information into
     * {@link IvyModuleInfo}, which will be then brought back to the master.
     */
    private static final class IvyXmlParser implements Callable<List<IvyModuleInfo>, Throwable> {
        private static final String IVY_XML_PATTERN = "**/ivy.xml";
        private final BuildListener listener;
        /**
         * Capture the value of the static field so that the debug flag takes an
         * effect even when {@link IvyXmlParser} runs in a slave.
         */
        private final boolean verbose = debug;
        private final String ivyFilePattern;
        private final String ivyFileExcludePattern;
        private final String ivySettingsFile;
        private final String ivySettingsPropertyFiles;
        private final String ivyBranch;
        private final String workspace;
        private final String workspaceProper;

        public IvyXmlParser(BuildListener listener, IvyModuleSet project, String workspace) {
            // project cannot be shipped to the remote JVM, so all the relevant
            // properties need to be captured now.
            this.listener = listener;
            this.ivyFilePattern = project.getIvyFilePattern() == null ? IVY_XML_PATTERN : project.getIvyFilePattern();
            this.ivyFileExcludePattern = project.getIvyFileExcludesPattern();
            this.ivyBranch = project.getIvyBranch();
            this.workspace = workspace;
            this.ivySettingsFile = project.getIvySettingsFile();
            this.ivySettingsPropertyFiles = project.getIvySettingsPropertyFiles();
            this.workspaceProper = project.getLastBuild().getWorkspace().getRemote();
        }

		@SuppressWarnings("unchecked")
        public List<IvyModuleInfo> call() throws Throwable {
			File ws = new File(workspace);
            FileSet ivyFiles = Util.createFileSet(ws, ivyFilePattern, ivyFileExcludePattern);
            final PrintStream logger = listener.getLogger();

            Ivy ivy = getIvy(logger);
            HashMap<ModuleDescriptor, String> moduleDescriptors = new HashMap<ModuleDescriptor, String>();
            for (String ivyFilePath : ivyFiles.getDirectoryScanner().getIncludedFiles()) {
                final File ivyFile = new File(ws, ivyFilePath);

                ModuleDescriptor module = (ModuleDescriptor) ivy.execute(new IvyCallback() {
                    public Object doInIvyContext(Ivy ivy, IvyContext context) {
                        try {
                            return ModuleDescriptorParserRegistry.getInstance().parseDescriptor(ivy.getSettings(), ivyFile.toURI().toURL(),
                                    ivy.getSettings().doValidate());
                        } catch (MalformedURLException e) {
                            logger.println("The URL is malformed : " + ivyFile);
                            return null;
                        } catch (ParseException e) {
                            logger.println("Parsing error while reading the ivy file " + ivyFile);
                            return null;
                        } catch (IOException e) {
                            logger.println("I/O error while reading the ivy file " + ivyFile);
                            return null;
                        }
                    }
                });
                moduleDescriptors.put(module, ivyFilePath.replace('\\', '/'));
            }

            List<IvyModuleInfo> infos = new ArrayList<IvyModuleInfo>();
            List<ModuleDescriptor> sortedModuleDescriptors = ivy.sortModuleDescriptors(moduleDescriptors.keySet(), SortOptions.DEFAULT);
            for (ModuleDescriptor moduleDescriptor : sortedModuleDescriptors) {
                infos.add(new IvyModuleInfo(moduleDescriptor, moduleDescriptors.get(moduleDescriptor)));
            }

            if (verbose) {
                for (IvyModuleInfo moduleInfo : infos) {
                    logger.printf("Discovered module %s at %s.\n", moduleInfo.displayName, moduleInfo.relativePathToDescriptor);
                }
            }

            return infos;
        }

        /**
         *
         * @return the Ivy instance based on the {@link #ivyConfName}
         * @throws AbortException
         *
         * @throws ParseException
         * @throws IOException
         */
        public Ivy getIvy(PrintStream logger) throws AbortException {
            Message.setDefaultLogger(new IvyMessageImpl());

            File settingsLoc = (ivySettingsFile == null) ? null : new File(workspaceProper, ivySettingsFile);

            if ((settingsLoc != null) && (!settingsLoc.exists())) {
                throw new AbortException(Messages.IvyModuleSetBuild_NoSuchIvySettingsFile(settingsLoc.getAbsolutePath()));
            }

            ArrayList<File> propertyFiles = new ArrayList<File>();
            if (StringUtils.isNotBlank(ivySettingsPropertyFiles)) {
                for (String file : ivySettingsPropertyFiles.split(",")) {
                    File propertyFile = new File(workspaceProper, file.trim());
                    if (!propertyFile.exists()) {
                        throw new AbortException(Messages.IvyModuleSetBuild_NoSuchPropertyFile(propertyFile.getAbsolutePath()));
                    }
                    propertyFiles.add(propertyFile);
                }
            }

            try {
                IvySettings ivySettings = new IvySettings();
                for (File file : propertyFiles) {
                    ivySettings.loadProperties(file);
                }
                if (settingsLoc != null) {
                    ivySettings.load(settingsLoc);
                    if (verbose)
                        logger.println("Configured Ivy using custom settings " + settingsLoc.getAbsolutePath());
                } else {
                    ivySettings.loadDefault();
                    if (verbose)
                        logger.println("Configured Ivy using default 2.1 settings");
                }
                if (ivyBranch != null) {
                    ivySettings.setDefaultBranch(ivyBranch);
                }
                return Ivy.newInstance(ivySettings);
            } catch (Exception e) {
                logger.println("Error while reading the default Ivy 2.1 settings: " + e.getMessage());
                logger.println(e.getStackTrace());
            }
            return null;
        }

        private static final long serialVersionUID = 1L;
    }

    private static final Logger LOGGER = Logger.getLogger(IvyModuleSetBuild.class.getName());

    /**
     * Extra verbose debug switch.
     */
    public static boolean debug = false;

    @Override
    public IvyModuleSet getParent() {// don't know why, but javac wants this
        return super.getParent();
    }

    private static final class IvyPreloadTask implements Callable<Boolean, IOException> {
		private static final long serialVersionUID = 1L;

		public Boolean call() throws IOException {
			try {
				return Channel.current().preloadJar(this, Ivy.class);
			} catch (InterruptedException e) {
			}
			return false;
		}
	}
}


text:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed><tipo>Rua</tipo><logradouro>Um</logradouro><bairro>Vila Calu</bairro><cidade>São Paulo</cidade><uf>SP</uf><cep>04961140</cep></feed>


text:
#include "icd-enumerate-drm.h"
#include "gpu.h"
#include "instance.h"

static int intel_devid_override;
int intel_debug = -1;

void *intel_alloc(const void *handle,
                                size_t size, size_t alignment,
                                VkSystemAllocationScope scope)
{
    assert(intel_handle_validate(handle));
    return icd_instance_alloc(((const struct intel_handle *) handle)->instance->icd,
            size, alignment, scope);
}

void intel_free(const void *handle, void *ptr)
{
    assert(intel_handle_validate(handle));
    icd_instance_free(((const struct intel_handle *) handle)->instance->icd, ptr);
}

void intel_logv(const void *handle,
                VkFlags msg_flags,
                VkDebugReportObjectTypeEXT obj_type, uint64_t src_object,
                size_t location, int32_t msg_code,
                const char *format, va_list ap)
{
    char msg[256];
    int ret;

    ret = vsnprintf(msg, sizeof(msg), format, ap);
    if (ret >= sizeof(msg) || ret < 0)
        msg[sizeof(msg) - 1] = '\0';

    assert(intel_handle_validate(handle));
    icd_instance_log(((const struct intel_handle *) handle)->instance->icd,
                     msg_flags,
                     obj_type, src_object,              /* obj_type, object */
                     location, msg_code,                /* location, msg_code */
                     msg);
}

static void intel_debug_init(void)
{
    const char *env;

    if (intel_debug >= 0)
        return;

    intel_debug = 0;

    /* parse comma-separated debug options */
    env = getenv("VK_INTEL_DEBUG");
    while (env) {
        const char *p = strchr(env, ',');
        size_t len;

        if (p)
            len = p - env;
        else
            len = strlen(env);

        if (len > 0) {
            if (strncmp(env, "batch", len) == 0) {
                intel_debug |= INTEL_DEBUG_BATCH;
            } else if (strncmp(env, "nohw", len) == 0) {
                intel_debug |= INTEL_DEBUG_NOHW;
            } else if (strncmp(env, "nocache", len) == 0) {
                intel_debug |= INTEL_DEBUG_NOCACHE;
            } else if (strncmp(env, "nohiz", len) == 0) {
                intel_debug |= INTEL_DEBUG_NOHIZ;
            } else if (strncmp(env, "hang", len) == 0) {
                intel_debug |= INTEL_DEBUG_HANG;
            } else if (strncmp(env, "0x", 2) == 0) {
                intel_debug |= INTEL_DEBUG_NOHW;
                intel_devid_override = strtol(env, NULL, 16);
            }
        }

        if (!p)
            break;

        env = p + 1;
    }
}

static void intel_instance_add_gpu(struct intel_instance *instance,
                                   struct intel_gpu *gpu)
{
    gpu->next = instance->gpus;
    instance->gpus = gpu;
}

static void intel_instance_remove_gpus(struct intel_instance *instance)
{
    struct intel_gpu *gpu = instance->gpus;

    while (gpu) {
        struct intel_gpu *next = gpu->next;

        intel_gpu_destroy(gpu);
        gpu = next;
    }

    instance->gpus = NULL;
}

static void intel_instance_destroy(struct intel_instance *instance)
{
    struct icd_instance *icd = instance->icd;

    intel_instance_remove_gpus(instance);
    icd_instance_free(icd, instance);

    icd_instance_destroy(icd);
}

static VkResult intel_instance_create(
        const VkInstanceCreateInfo* info,
        const VkAllocationCallbacks* allocator,
        struct intel_instance **pInstance)
{
    struct intel_instance *instance;
    struct icd_instance *icd;
    uint32_t i;

    intel_debug_init();

    icd = icd_instance_create(info->pApplicationInfo, allocator);
    if (!icd)
        return VK_ERROR_OUT_OF_HOST_MEMORY;

    instance = icd_instance_alloc(icd, sizeof(*instance), sizeof(int),
            VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    if (!instance) {
        icd_instance_destroy(icd);
        return VK_ERROR_OUT_OF_HOST_MEMORY;
    }

    memset(instance, 0, sizeof(*instance));
    intel_handle_init(&instance->handle, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, instance);

    instance->icd = icd;

    for (i = 0; i < info->enabledExtensionCount; i++) {
        const enum intel_global_ext_type ext =
            intel_gpu_lookup_global_extension(
                    info->ppEnabledExtensionNames[i]);

        if (ext != INTEL_GLOBAL_EXT_INVALID) {
            instance->global_exts[ext] = true;
        } else {
            /* Fail create if extensions are specified that
             * ICD cannot satisfy. Loader will filter out extensions / layers
             * not meant by the ICD.
             */
            icd_instance_destroy(icd);
            intel_instance_destroy(instance);
            return VK_ERROR_EXTENSION_NOT_PRESENT;
        }
    }

    /*
     * This ICD does not support any layers.
     */
    if (info->enabledLayerCount > 0) {
        icd_instance_destroy(icd);
        intel_instance_destroy(instance);
        return VK_ERROR_LAYER_NOT_PRESENT;
    }

    *pInstance = instance;

    return VK_SUCCESS;
}

enum intel_global_ext_type intel_gpu_lookup_global_extension(
        const char *extensionName)
{
    enum intel_global_ext_type type;

    for (type = 0; type < ARRAY_SIZE(intel_global_exts); type++) {
        if (compare_vk_extension_properties(&intel_global_exts[type], extensionName))
            break;
    }

    assert(type < INTEL_GLOBAL_EXT_COUNT || type == INTEL_GLOBAL_EXT_INVALID);

    return type;
}

VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
    const VkInstanceCreateInfo*               pCreateInfo,
    const VkAllocationCallbacks*              pAllocator,
    VkInstance*                               pInstance)
{
    return intel_instance_create(pCreateInfo, pAllocator,
            (struct intel_instance **) pInstance);
}

VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
    VkInstance                                pInstance,
    const VkAllocationCallbacks*              pAllocator)
{
    struct intel_instance *instance = intel_instance(pInstance);

    intel_instance_destroy(instance);
}

VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
        const char*                           pLayerName,
        uint32_t*                             pPropertyCount,
        VkExtensionProperties*                pProperties)
{
    uint32_t copy_size;

    if (pProperties == NULL) {
        *pPropertyCount = INTEL_GLOBAL_EXT_COUNT;
        return VK_SUCCESS;
    }

    copy_size = *pPropertyCount < INTEL_GLOBAL_EXT_COUNT ? *pPropertyCount : INTEL_GLOBAL_EXT_COUNT;
    memcpy(pProperties, intel_global_exts, copy_size * sizeof(VkExtensionProperties));
    *pPropertyCount = copy_size;
    if (copy_size < INTEL_GLOBAL_EXT_COUNT) {
        return VK_INCOMPLETE;
    }

    return VK_SUCCESS;
}

VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
        uint32_t*                             pPropertyCount,
        VkLayerProperties*                    pProperties)
{
    *pPropertyCount = 0;
    return VK_SUCCESS;
}

static VkPhysicalDevice physicalGPU = 0;

VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
    VkInstance                                instance_,
    uint32_t*                                 pPhysicalDeviceCount,
    VkPhysicalDevice*                         pPhysicalDevices)
{
    struct intel_instance *instance = intel_instance(instance_);
    struct icd_drm_device *devices, *dev;
    VkResult ret;
    uint32_t count;

    if (pPhysicalDevices == NULL) {
        *pPhysicalDeviceCount = 1;
        return VK_SUCCESS;
    }

    if (physicalGPU)
    {
        *pPhysicalDeviceCount = 1;
        pPhysicalDevices[0] = physicalGPU;
        return VK_SUCCESS;
    }

    intel_instance_remove_gpus(instance);

    devices = icd_drm_enumerate(instance->icd, 0x8086);

    count = 0;
    dev = devices;
    while (dev) {
        const char *primary_node, *render_node;
        int devid;
        struct intel_gpu *gpu;

        primary_node = icd_drm_get_devnode(dev, ICD_DRM_MINOR_LEGACY);
        if (!primary_node)
            continue;

        render_node = icd_drm_get_devnode(dev, ICD_DRM_MINOR_RENDER);

        devid = (intel_devid_override) ? intel_devid_override : dev->devid;
        ret = intel_gpu_create(instance, devid,
                primary_node, render_node, &gpu);
        if (ret == VK_SUCCESS) {
            intel_instance_add_gpu(instance, gpu);

            pPhysicalDevices[count++] = (VkPhysicalDevice) gpu;
            physicalGPU = (VkPhysicalDevice) gpu;
            if (count >= *pPhysicalDeviceCount)
                break;
        }

        dev = dev->next;
    }

    icd_drm_release(instance->icd, devices);

    *pPhysicalDeviceCount = count;

    return VK_SUCCESS;
}

VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
    VkInstance                                instance,
    const VkDebugReportCallbackCreateInfoEXT  *pCreateInfo,
    const VkAllocationCallbacks*              pAllocator,
    VkDebugReportCallbackEXT*                 pCallback)
{
    struct intel_instance *inst = intel_instance(instance);

    return icd_instance_create_logger(inst->icd, pCreateInfo, pAllocator, pCallback);
}

VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(
    VkInstance                                instance,
    VkDebugReportCallbackEXT                  callback,
    const VkAllocationCallbacks               *pAllocator)
{
    struct intel_instance *inst = intel_instance(instance);

    icd_instance_destroy_logger(inst->icd, callback, pAllocator);
}

VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
    VkInstance                                instance,
    VkDebugReportFlagsEXT                     flags,
    VkDebugReportObjectTypeEXT                objType,
    uint64_t                                  object,
    size_t                                    location,
    int32_t                                   msgCode,
    const char*                               pLayerPrefix,
    const char*                               pMsg)
{
    // Intentionally does nothing.
    // Loader will call registered callbacks after all
    // ICDs have been notified.
}


text:
package com.facebook.buck.parser;

import static org.junit.Assert.assertEquals;

import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.google.common.collect.ImmutableSet;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class BuildFileSpecTest {

  @Rule
  public TemporaryFolder tmp = new TemporaryFolder();

  @Test
  public void recursiveVsNonRecursive() throws IOException {
    FakeProjectFilesystem filesystem = new FakeProjectFilesystem();
    Path buildFile = Paths.get("a", "BUCK");
    filesystem.mkdirs(buildFile.getParent());
    filesystem.touch(buildFile);

    Path nestedBuildFile = Paths.get("a", "b", "BUCK");
    filesystem.mkdirs(nestedBuildFile.getParent());
    filesystem.touch(nestedBuildFile);

    // Test a non-recursive spec.
    BuildFileSpec nonRecursiveSpec = BuildFileSpec.fromPath(buildFile.getParent());
    ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(buildFile);
    ImmutableSet<Path> actualBuildFiles = nonRecursiveSpec.findBuildFiles(filesystem, "BUCK");
    assertEquals(expectedBuildFiles, actualBuildFiles);

    // Test a recursive spec.
    BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent());
    expectedBuildFiles = ImmutableSet.of(buildFile, nestedBuildFile);
    actualBuildFiles = recursiveSpec.findBuildFiles(filesystem, "BUCK");
    assertEquals(expectedBuildFiles, actualBuildFiles);
  }

  @Test
  public void recursiveIgnorePaths() throws IOException {
    // NOTE(agallagher): FakeProjectFilesystem doesn't currently support a proper walkFileTree
    // method, so use a real one here to test ignore dirs.
    ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot().toPath());
    Path buildFile = Paths.get("a", "BUCK");
    filesystem.mkdirs(buildFile.getParent());
    filesystem.writeContentsToPath("", buildFile);

    Path ignoredBuildFile = Paths.get("a", "b", "BUCK");
    filesystem.mkdirs(ignoredBuildFile.getParent());
    filesystem.writeContentsToPath("", ignoredBuildFile);

    // Test a recursive spec with an ignored dir.
    ImmutableSet<Path> ignore = ImmutableSet.of(ignoredBuildFile.getParent());
    BuildFileSpec recursiveSpec = BuildFileSpec.fromRecursivePath(buildFile.getParent(), ignore);
    ImmutableSet<Path> expectedBuildFiles = ImmutableSet.of(buildFile);
    ImmutableSet<Path> actualBuildFiles = recursiveSpec.findBuildFiles(filesystem, "BUCK");
    assertEquals(expectedBuildFiles, actualBuildFiles);
  }

}


text:
<?xml version="1.0"?>
<config>
	<modules>
		<Bitbull_Soisy>
			<version>0.6.2</version>
		</Bitbull_Soisy>
	</modules>
	<global>
		<models>
			<soisy>
				<class>Bitbull_Soisy_Model</class>
			</soisy>
		</models>
		<blocks>
			<soisy>
				<class>Bitbull_Soisy_Block</class>
			</soisy>
		</blocks>
		<helpers>
			<soisy>
				<class>Bitbull_Soisy_Helper</class>
			</soisy>
		</helpers>
		<resources>
			<soisy_setup>
				<setup>
					<module>Bitbull_Soisy</module>
					<class>Bitbull_Soisy_Model_Resource_Setup</class>
				</setup>
			</soisy_setup>
		</resources>
	</global>
	<frontend>
		<layout>
			<updates>
				<soisy>
					<file>soisy.xml</file>
				</soisy>
			</updates>
		</layout>
		<events>
			<checkout_onepage_controller_success_action>
				<observers>
					<soisy_redirect>
						<class>soisy/observer</class>
						<method>setOrdersIds</method>
					</soisy_redirect>
				</observers>
			</checkout_onepage_controller_success_action>
		</events>
		<routers>
			<soisy>
				<use>standard</use>
				<args>
					<frontName>soisy</frontName>
					<module>Bitbull_Soisy</module>
				</args>
			</soisy>
		</routers>
		<translate>
			<modules>
				<Bitbull_Soisy>
					<files>
						<default>Bitbull_Soisy.csv</default>
					</files>
				</Bitbull_Soisy>
			</modules>
		</translate>
	</frontend>
    <adminhtml>
		<translate>
			<modules>
				<Bitbull_Soisy>
					<files>
						<default>Bitbull_Soisy.csv</default>
					</files>
				</Bitbull_Soisy>
			</modules>
		</translate>
	</adminhtml>

	<default>
		<payment>
			<soisy>
				<active>0</active>
				<model>soisy/soisy</model>
				<percentage>100</percentage>
				<order_status>pending</order_status>
				<title>Finanziamento con Soisy</title>
				<terms_and_conditions>https://www.soisy.it/privacy-policy/</terms_and_conditions>
				<allowspecific>0</allowspecific>
				<group>offline</group>
				<instalments>12</instalments>
				<zero_interest>0</zero_interest>
				<min_order_total>250</min_order_total>
				<max_order_total>20000</max_order_total>
				<loan_quote_placement>price-box</loan_quote_placement>
				<checkout_loan_quote_placement>checkout-review-table</checkout_loan_quote_placement>
				<cart_loan_quote_placement>cart-totals #shopping-cart-totals-table</cart_loan_quote_placement>
				<information_about_loan>min</information_about_loan>
				<loan_quote_text_checkout>You can also pay instalments, eg  {INSTALMENT_AMOUNT}, in {INSTALMENT_PERIOD} months, with a total cost of {TOTAL_REPAID} and TAEG {TAEG}. Just choose "Pay with Soisy" when choosing the payment method</loan_quote_text_checkout>
				<loan_quote_text_cart>You can also pay instalments, eg  {INSTALMENT_AMOUNT}, in {INSTALMENT_PERIOD} months, with a total cost of {TOTAL_REPAID} and TAEG {TAEG}. Just choose "Pay with Soisy" when choosing the payment method</loan_quote_text_cart>
				<loan_quote_text_product>You can also pay instalments, eg  {INSTALMENT_AMOUNT}, in {INSTALMENT_PERIOD} months, with a total cost of {TOTAL_REPAID} and TAEG {TAEG}. Just choose "Pay with Soisy" when choosing the payment method</loan_quote_text_product>
				<sandbox_mode>0</sandbox_mode>
			</soisy>
		</payment>
	</default>
</config>