ifneq (,)
.error This Makefile requires GNU Make.
endif

# -------------------------------------------------------------------------------------------------
# Docker configuration
# -------------------------------------------------------------------------------------------------

DIR = Dockerfiles
IMAGE = devilbox/php-fpm
NO_CACHE =
PHP_EXT_DIR =

# Run checks after each module has been installed (slow, but yields errors faster)
FAIL_FAST = False

# -------------------------------------------------------------------------------------------------
#  DEFAULT TARGET
# -------------------------------------------------------------------------------------------------

help:
	@echo
	@echo "             _         _ _ _            __   _           ___          "
	@echo "           _| |___ _ _<_| | |_ _____   / ___| |_ ___ ___| | ___._ _ _ "
	@echo "          / . / ._| | | | | . / . \ \// | . | . | . |___| || . | ' ' |"
	@echo "          \___\___|__/|_|_|___\___/\_/_/|  _|_|_|  _/   |_||  _|_|_|_|"
	@echo "                                        |_|     |_|        |_|        "
	@echo
	@echo
	@echo "Targets"
	@echo "--------------------------------------------------------------------------------"
	@echo
	@echo "gen-readme [VERSION=]         Update README with PHP modules from built images."
	@echo "gen-dockerfiles [FAIL_FAST=]  Generate Dockerfiles from templates."
	@echo
	@echo "build-base VERSION= [ARGS=]   Build base image by specified version"
	@echo "build-mods VERSION= [ARGS=]   Build mods image by specified version"
	@echo "build-prod VERSION= [ARGS=]   Build prod image by specified version"
	@echo "build-work VERSION= [ARGS=]   Build work image by specified version"
	@echo
	@echo "rebuild-base VERSION= [ARGS=] Rebuild base image by specified version"
	@echo "rebuild-mods VERSION= [ARGS=] Rebuild mods image by specified version"
	@echo "rebuild-prod VERSION= [ARGS=] Rebuild prod image by specified version"
	@echo "rebuild-work VERSION= [ARGS=] Rebuild work image by specified version"
	@echo
	@echo "test-base VERSION=            Test base image by specified version"
	@echo "test-mods VERSION=            Test mods image by specified version"
	@echo "test-prod VERSION=            Test prod image by specified version"
	@echo "test-work VERSION=            Test work image by specified version"
	@echo
	@echo
	@echo "Variables"
	@echo "--------------------------------------------------------------------------------"
	@echo
	@echo "VERSION                       One of '5.2', '5.3', '5.4', '5.5', '5.6', '7.0',"
	@echo "                                      '7.1', '7.2', '7.3', '7.4', '8.0'."
	@echo "                              For gen-readme target it is optional and if not"
	@echo "                              specified, it will generate for all versions."
	@echo
	@echo "FAIL_FAST                     Either 'True' or 'False' (defaults to 'False')."
	@echo "                              If set to 'True', each module install has an"
	@echo "                              immediate check, which is very slow for CI, but"
	@echo "                              yields errors immediately."
	@echo "                              If set to 'False', checks are done at the end."
	@echo
	@echo "ARGS                          Can be added to all build-* and rebuild-* targets"
	@echo "                              to supply additional docker build options."

# -------------------------------------------------------------------------------------------------
#  GENERATE TARGETS
# -------------------------------------------------------------------------------------------------

gen-readme:
ifeq ($(strip $(VERSION)),)
	@echo "Generate README.md for all PHP versions"
	cd build; ./gen-readme.sh
else
	@echo "Generate README.md for PHP $(VERSION)"
	@$(MAKE) --no-print-directory _check-version
	@$(MAKE) --no-print-directory _check-image-exists _EXIST_IMAGE=base
	@$(MAKE) --no-print-directory _check-image-exists _EXIST_IMAGE=mods
	cd build; ./gen-readme.sh $(VERSION)
endif

gen-dockerfiles:
	docker run --rm \
		$$(tty -s && echo "-it" || echo) \
		-e USER=ansible \
		-e MY_UID=$$(id -u) \
		-e MY_GID=$$(id -g) \
		-v ${PWD}:/data \
		-w /data/build/ansible \
		cytopia/ansible:2.6-tools ansible-playbook generate.yml \
			-e ANSIBLE_STRATEGY_PLUGINS=/usr/lib/python3.6/site-packages/ansible_mitogen/plugins/strategy \
			-e ANSIBLE_STRATEGY=mitogen_linear \
			-e ansible_python_interpreter=/usr/bin/python3 \
			-e \"{build_fail_fast: $(FAIL_FAST)}\" \
			--diff $(ARGS)

# -------------------------------------------------------------------------------------------------
#  BUILD TARGETS
# -------------------------------------------------------------------------------------------------

build-base: _check-version
build-base:
	docker build $(NO_CACHE) \
		--label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \
		--label "org.opencontainers.image.version"="$$(git rev-parse --abbrev-ref HEAD)" \
		--label "org.opencontainers.image.revision"="$$(git rev-parse HEAD))" \
		$(ARGS) \
		-t $(IMAGE):${VERSION}-base \
		-f $(DIR)/base/Dockerfile-${VERSION} $(DIR)/base

build-mods: _check-version
build-mods: _EXIST_IMAGE=base
build-mods: _check-image-exists
build-mods:
ifeq ($(strip $(TARGET)),)
	docker build $(NO_CACHE) \
		--target builder \
		-t $(IMAGE):$(VERSION)-mods \
		-f $(DIR)/mods/Dockerfile-$(VERSION) $(DIR)/mods;
	@# $(NO_CACHE) is removed, as it would otherwise rebuild the 'builder' image again.
	docker build \
		--target final \
		--label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \
		--label "org.opencontainers.image.version"="$$(git rev-parse --abbrev-ref HEAD)" \
		--label "org.opencontainers.image.revision"="$$(git rev-parse HEAD)" \
		--build-arg EXT_DIR="$$( docker run --rm --entrypoint=php $(IMAGE):$(VERSION)-mods -i \
			| grep ^extension_dir \
			| awk -F '=>' '{print $$2}' \
			| xargs \
		)" \
		$(ARGS) \
		-t $(IMAGE):$(VERSION)-mods \
		-f $(DIR)/mods/Dockerfile-$(VERSION) $(DIR)/mods;
else
	docker build $(NO_CACHE) \
		--target $(TARGET) \
		--label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \
		--label "org.opencontainers.image.version"="$$(git rev-parse --abbrev-ref HEAD)" \
		--label "org.opencontainers.image.revision"="$$(git rev-parse HEAD)" \
		$(ARGS) \
		-t $(IMAGE):$(VERSION)-mods \
		-f $(DIR)/mods/Dockerfile-$(VERSION) $(DIR)/mods
endif

build-prod: _check-version
build-prod: _EXIST_IMAGE=mods
build-prod: _check-image-exists
build-prod:
	docker build $(NO_CACHE) \
		--label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \
		--label "org.opencontainers.image.version"="$$(git rev-parse --abbrev-ref HEAD)" \
		--label "org.opencontainers.image.revision"="$$(git rev-parse HEAD)" \
		$(ARGS) \
		-t $(IMAGE):${VERSION}-prod \
		-f $(DIR)/prod/Dockerfile-${VERSION} $(DIR)/prod

build-work: _check-version
build-work: _EXIST_IMAGE=prod
build-work: _check-image-exists
build-work:
	docker build $(NO_CACHE) \
		--label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \
		--label "org.opencontainers.image.version"="$$(git rev-parse --abbrev-ref HEAD)" \
		--label "org.opencontainers.image.revision"="$$(git rev-parse HEAD)" \
		$(ARGS) \
		-t $(IMAGE):${VERSION}-work \
		-f $(DIR)/work/Dockerfile-${VERSION} $(DIR)/work

# -------------------------------------------------------------------------------------------------
#  REBUILD TARGETS
# -------------------------------------------------------------------------------------------------

rebuild-base: _pull-root-image
rebuild-base: NO_CACHE=--no-cache
rebuild-base: build-base

rebuild-mods: NO_CACHE=--no-cache
rebuild-mods: build-mods

rebuild-prod: NO_CACHE=--no-cache
rebuild-prod: build-prod

rebuild-work: NO_CACHE=--no-cache
rebuild-work: build-work

# -------------------------------------------------------------------------------------------------
#  TEST TARGETS
# -------------------------------------------------------------------------------------------------

test-base: _check-version
test-base: _EXIST_IMAGE=base
test-base: _check-image-exists
test-base:
	./tests/test.sh ${VERSION} base

test-mods: _check-version
test-mods: _EXIST_IMAGE=mods
test-mods: _check-image-exists
test-mods: _check-version
	./tests/test.sh ${VERSION} mods

test-prod: _check-version
test-prod: _EXIST_IMAGE=prod
test-prod: _check-image-exists
test-prod: _check-version
	./tests/test.sh ${VERSION} prod

test-work: _check-version
test-work: _EXIST_IMAGE=work
test-work: _check-image-exists
test-work: _check-version
	./tests/test.sh ${VERSION} work

# -------------------------------------------------------------------------------------------------
#  DOCKERHUB TARGETS
# -------------------------------------------------------------------------------------------------
login:
ifeq ($(strip $(USERNAME)),)
	@$(info This make target requires the USERNAME variable to be set.)
	@$(info make login USERNAME= PASSWORD=)
	@$(info )
	@$(error Exiting)
endif
ifeq ($(strip $(PASSWORD)),)
	@$(info This make target requires the PASSWORD variable to be set.)
	@$(info make login USERNAME= PASSWORD=)
	@$(info )
	@$(error Exiting)
endif
	@yes | docker login --username $(USERNAME) --password $(PASSWORD)

push:
ifeq ($(strip $(TAG)),)
	@$(info This make target requires the TAG variable to be set.)
	@$(info make push TAG=)
	@$(info )
	@$(error Exiting)
endif
	docker push $(IMAGE):$(TAG)

tag:
ifeq ($(strip $(OLD_TAG)),)
	@$(info This make target requires the OLD_TAG variable to be set.)
	@$(info make tag OLD_TAG= NEW_TAG=)
	@$(info )
	@$(error Exiting)
endif
ifeq ($(strip $(NEW_TAG)),)
	@$(info This make target requires the NEW_TAG variable to be set.)
	@$(info make tag OLD_TAG= NEW_TAG=)
	@$(info )
	@$(error Exiting)
endif
	docker tag $(IMAGE):$(OLD_TAG) $(IMAGE):$(NEW_TAG)

# -------------------------------------------------------------------------------------------------
#  HELPER TARGETS
# -------------------------------------------------------------------------------------------------

_check-version:
ifeq ($(strip $(VERSION)),)
	@$(info This make target requires the VERSION variable to be set.)
	@$(info make build-<flavour> VERSION=7.3)
	@$(info )
	@$(error Exiting)
endif
ifeq ($(VERSION),5.2)
else
ifeq ($(VERSION),5.3)
else
ifeq ($(VERSION),5.4)
else
ifeq ($(VERSION),5.5)
else
ifeq ($(VERSION),5.6)
else
ifeq ($(VERSION),7.0)
else
ifeq ($(VERSION),7.1)
else
ifeq ($(VERSION),7.2)
else
ifeq ($(VERSION),7.3)
else
ifeq ($(VERSION),7.4)
else
ifeq ($(VERSION),8.0)
else
	@$(info VERSION can only be: '5.2', '5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4' or '8.0')
	@$(info )
	@$(error Exiting)
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif
	@echo "Version $(VERSION) is valid"

_check-image-exists:
	@if [ "$$(docker images -q $(IMAGE):$(VERSION)-$(_EXIST_IMAGE))" = "" ]; then \
		>&2 echo "Docker image '$(IMAGE):$(VERSION)-$(_EXIST_IMAGE)' was not found locally."; \
		>&2 echo "Either build it first or explicitly pull it from Dockerhub."; \
		>&2 echo "This is a safeguard to not automatically pull the Docker image."; \
		>&2 echo; \
		false; \
	fi;

_pull-root-image:
	@echo "Pulling root image for PHP ${VERSION}"
	@docker pull $(shell grep FROM $(DIR)/base/Dockerfile-${VERSION} | sed 's/^FROM\s*//g';)

{'repo_name': 'devilbox/docker-php-fpm', 'stars': '160', 'repo_language': 'Roff', 'file_name': '02-test-env-uid.sh', 'mime_type': 'text/x-shellscript', 'hash': 6823708819686477072, 'source_dataset': 'data'}


<sparql xmlns='http://www.w3.org/2005/sparql-results#'>
<head>
<variable name='x'/>
<variable name='y'/>
<variable name='z'/>
<variable name='eq'/>
</head>
<results>
<result>
<binding name='x'><uri>http://www.example.org/instance#a</uri></binding>
<binding name='y'><literal datatype='http://www.w3.org/2001/XMLSchema#integer'>1</literal></binding>
<binding name='z'><literal datatype='http://www.w3.org/2001/XMLSchema#integer'>1</literal></binding>
<binding name='eq'><literal datatype='http://www.w3.org/2001/XMLSchema#boolean'>true</literal></binding>
</result>
<result>
<binding name='x'><uri>http://www.example.org/instance#a</uri></binding>
<binding name='y'><literal datatype='http://www.w3.org/2001/XMLSchema#integer'>1</literal></binding>
<binding name='z'><literal datatype='http://www.w3.org/2001/XMLSchema#integer'>2</literal></binding>
<binding name='eq'><literal datatype='http://www.w3.org/2001/XMLSchema#boolean'>false</literal></binding>
</result>
</results>
</sparql>

{'repo_name': 'BrightstarDB/BrightstarDB', 'stars': '409', 'repo_language': 'C#', 'file_name': 'AssemblyInfo.cs', 'mime_type': 'text/plain', 'hash': -2377769300866239864, 'source_dataset': 'data'}


### `tf.listdiff(x, y, name=None)` {#listdiff}

Computes the difference between two lists of numbers or strings.

Given a list `x` and a list `y`, this operation returns a list `out` that
represents all values that are in `x` but not in `y`. The returned list `out`
is sorted in the same order that the numbers appear in `x` (duplicates are
preserved). This operation also returns a list `idx` that represents the
position of each `out` element in `x`. In other words:

`out[i] = x[idx[i]] for i in [0, 1, ..., len(out) - 1]`

For example, given this input:

```prettyprint
x = [1, 2, 3, 4, 5, 6]
y = [1, 3, 5]
```

This operation would return:

```prettyprint
out ==> [2, 4, 6]
idx ==> [1, 3, 5]
```

##### Args:

*  <b>`x`</b>: A `Tensor`. 1-D. Values to keep.
*  <b>`y`</b>: A `Tensor`. Must have the same type as `x`. 1-D. Values to remove.
*  <b>`name`</b>: A name for the operation (optional).

##### Returns:

  A tuple of `Tensor` objects (out, idx).

*  <b>`out`</b>: A `Tensor`. Has the same type as `x`. 1-D. Values present in `x` but not in `y`.
*  <b>`idx`</b>: A `Tensor` of type `int32`. 1-D. Positions of `x` values preserved in `out`.

{'repo_name': 'natanielruiz/android-yolo', 'stars': '574', 'repo_language': 'C++', 'file_name': 'workspace.xml', 'mime_type': 'text/xml', 'hash': -3785837904622230066, 'source_dataset': 'data'}


// Copyright 2009,2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// NetBSD system calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates system call stubs.
// Note that sometimes we use a lowercase //sys name and wrap
// it in our own nicer implementation, either here or in
// syscall_bsd.go or syscall_unix.go.

package unix

import (
	"syscall"
	"unsafe"
)

type SockaddrDatalink struct {
	Len    uint8
	Family uint8
	Index  uint16
	Type   uint8
	Nlen   uint8
	Alen   uint8
	Slen   uint8
	Data   [12]int8
	raw    RawSockaddrDatalink
}

func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)

func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
	var olen uintptr

	// Get a list of all sysctl nodes below the given MIB by performing
	// a sysctl for the given MIB with CTL_QUERY appended.
	mib = append(mib, CTL_QUERY)
	qnode := Sysctlnode{Flags: SYSCTL_VERS_1}
	qp := (*byte)(unsafe.Pointer(&qnode))
	sz := unsafe.Sizeof(qnode)
	if err = sysctl(mib, nil, &olen, qp, sz); err != nil {
		return nil, err
	}

	// Now that we know the size, get the actual nodes.
	nodes = make([]Sysctlnode, olen/sz)
	np := (*byte)(unsafe.Pointer(&nodes[0]))
	if err = sysctl(mib, np, &olen, qp, sz); err != nil {
		return nil, err
	}

	return nodes, nil
}

func nametomib(name string) (mib []_C_int, err error) {

	// Split name into components.
	var parts []string
	last := 0
	for i := 0; i < len(name); i++ {
		if name[i] == '.' {
			parts = append(parts, name[last:i])
			last = i + 1
		}
	}
	parts = append(parts, name[last:])

	// Discover the nodes and construct the MIB OID.
	for partno, part := range parts {
		nodes, err := sysctlNodes(mib)
		if err != nil {
			return nil, err
		}
		for _, node := range nodes {
			n := make([]byte, 0)
			for i := range node.Name {
				if node.Name[i] != 0 {
					n = append(n, byte(node.Name[i]))
				}
			}
			if string(n) == part {
				mib = append(mib, _C_int(node.Num))
				break
			}
		}
		if len(mib) != partno+1 {
			return nil, EINVAL
		}
	}

	return mib, nil
}

func direntIno(buf []byte) (uint64, bool) {
	return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
}

func direntReclen(buf []byte) (uint64, bool) {
	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}

func direntNamlen(buf []byte) (uint64, bool) {
	return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}

//sysnb pipe() (fd1 int, fd2 int, err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	p[0], p[1], err = pipe()
	return
}

//sys getdents(fd int, buf []byte) (n int, err error)
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
	return getdents(fd, buf)
}

// TODO
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
	return -1, ENOSYS
}

func setattrlistTimes(path string, times []Timespec, flags int) error {
	// used on Darwin for UtimesNano
	return ENOSYS
}

/*
 * Exposed directly
 */
//sys	Access(path string, mode uint32) (err error)
//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
//sys	Chdir(path string) (err error)
//sys	Chflags(path string, flags int) (err error)
//sys	Chmod(path string, mode uint32) (err error)
//sys	Chown(path string, uid int, gid int) (err error)
//sys	Chroot(path string) (err error)
//sys	Close(fd int) (err error)
//sys	Dup(fd int) (nfd int, err error)
//sys	Dup2(from int, to int) (err error)
//sys	Exit(code int)
//sys	Fchdir(fd int) (err error)
//sys	Fchflags(fd int, flags int) (err error)
//sys	Fchmod(fd int, mode uint32) (err error)
//sys	Fchown(fd int, uid int, gid int) (err error)
//sys	Flock(fd int, how int) (err error)
//sys	Fpathconf(fd int, name int) (val int, err error)
//sys	Fstat(fd int, stat *Stat_t) (err error)
//sys	Fsync(fd int) (err error)
//sys	Ftruncate(fd int, length int64) (err error)
//sysnb	Getegid() (egid int)
//sysnb	Geteuid() (uid int)
//sysnb	Getgid() (gid int)
//sysnb	Getpgid(pid int) (pgid int, err error)
//sysnb	Getpgrp() (pgrp int)
//sysnb	Getpid() (pid int)
//sysnb	Getppid() (ppid int)
//sys	Getpriority(which int, who int) (prio int, err error)
//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
//sysnb	Getrusage(who int, rusage *Rusage) (err error)
//sysnb	Getsid(pid int) (sid int, err error)
//sysnb	Gettimeofday(tv *Timeval) (err error)
//sysnb	Getuid() (uid int)
//sys	Issetugid() (tainted bool)
//sys	Kill(pid int, signum syscall.Signal) (err error)
//sys	Kqueue() (fd int, err error)
//sys	Lchown(path string, uid int, gid int) (err error)
//sys	Link(path string, link string) (err error)
//sys	Listen(s int, backlog int) (err error)
//sys	Lstat(path string, stat *Stat_t) (err error)
//sys	Mkdir(path string, mode uint32) (err error)
//sys	Mkfifo(path string, mode uint32) (err error)
//sys	Mknod(path string, mode uint32, dev int) (err error)
//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys	Open(path string, mode int, perm uint32) (fd int, err error)
//sys	Pathconf(path string, name int) (val int, err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys	read(fd int, p []byte) (n int, err error)
//sys	Readlink(path string, buf []byte) (n int, err error)
//sys	Rename(from string, to string) (err error)
//sys	Revoke(path string) (err error)
//sys	Rmdir(path string) (err error)
//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
//sysnb	Setegid(egid int) (err error)
//sysnb	Seteuid(euid int) (err error)
//sysnb	Setgid(gid int) (err error)
//sysnb	Setpgid(pid int, pgid int) (err error)
//sys	Setpriority(which int, who int, prio int) (err error)
//sysnb	Setregid(rgid int, egid int) (err error)
//sysnb	Setreuid(ruid int, euid int) (err error)
//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
//sysnb	Setsid() (pid int, err error)
//sysnb	Settimeofday(tp *Timeval) (err error)
//sysnb	Setuid(uid int) (err error)
//sys	Stat(path string, stat *Stat_t) (err error)
//sys	Symlink(path string, link string) (err error)
//sys	Sync() (err error)
//sys	Truncate(path string, length int64) (err error)
//sys	Umask(newmask int) (oldmask int)
//sys	Unlink(path string) (err error)
//sys	Unmount(path string, flags int) (err error)
//sys	write(fd int, p []byte) (n int, err error)
//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
//sys	munmap(addr uintptr, length uintptr) (err error)
//sys	readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys	writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys	utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)

/*
 * Unimplemented
 */
// ____semctl13
// __clone
// __fhopen40
// __fhstat40
// __fhstatvfs140
// __fstat30
// __getcwd
// __getfh30
// __getlogin
// __lstat30
// __mount50
// __msgctl13
// __msync13
// __ntp_gettime30
// __posix_chown
// __posix_fadvise50
// __posix_fchown
// __posix_lchown
// __posix_rename
// __setlogin
// __shmctl13
// __sigaction_sigtramp
// __sigaltstack14
// __sigpending14
// __sigprocmask14
// __sigsuspend14
// __sigtimedwait
// __stat30
// __syscall
// __vfork14
// _ksem_close
// _ksem_destroy
// _ksem_getvalue
// _ksem_init
// _ksem_open
// _ksem_post
// _ksem_trywait
// _ksem_unlink
// _ksem_wait
// _lwp_continue
// _lwp_create
// _lwp_ctl
// _lwp_detach
// _lwp_exit
// _lwp_getname
// _lwp_getprivate
// _lwp_kill
// _lwp_park
// _lwp_self
// _lwp_setname
// _lwp_setprivate
// _lwp_suspend
// _lwp_unpark
// _lwp_unpark_all
// _lwp_wait
// _lwp_wakeup
// _pset_bind
// _sched_getaffinity
// _sched_getparam
// _sched_setaffinity
// _sched_setparam
// acct
// aio_cancel
// aio_error
// aio_fsync
// aio_read
// aio_return
// aio_suspend
// aio_write
// break
// clock_getres
// clock_gettime
// clock_settime
// compat_09_ogetdomainname
// compat_09_osetdomainname
// compat_09_ouname
// compat_10_omsgsys
// compat_10_osemsys
// compat_10_oshmsys
// compat_12_fstat12
// compat_12_getdirentries
// compat_12_lstat12
// compat_12_msync
// compat_12_oreboot
// compat_12_oswapon
// compat_12_stat12
// compat_13_sigaction13
// compat_13_sigaltstack13
// compat_13_sigpending13
// compat_13_sigprocmask13
// compat_13_sigreturn13
// compat_13_sigsuspend13
// compat_14___semctl
// compat_14_msgctl
// compat_14_shmctl
// compat_16___sigaction14
// compat_16___sigreturn14
// compat_20_fhstatfs
// compat_20_fstatfs
// compat_20_getfsstat
// compat_20_statfs
// compat_30___fhstat30
// compat_30___fstat13
// compat_30___lstat13
// compat_30___stat13
// compat_30_fhopen
// compat_30_fhstat
// compat_30_fhstatvfs1
// compat_30_getdents
// compat_30_getfh
// compat_30_ntp_gettime
// compat_30_socket
// compat_40_mount
// compat_43_fstat43
// compat_43_lstat43
// compat_43_oaccept
// compat_43_ocreat
// compat_43_oftruncate
// compat_43_ogetdirentries
// compat_43_ogetdtablesize
// compat_43_ogethostid
// compat_43_ogethostname
// compat_43_ogetkerninfo
// compat_43_ogetpagesize
// compat_43_ogetpeername
// compat_43_ogetrlimit
// compat_43_ogetsockname
// compat_43_okillpg
// compat_43_olseek
// compat_43_ommap
// compat_43_oquota
// compat_43_orecv
// compat_43_orecvfrom
// compat_43_orecvmsg
// compat_43_osend
// compat_43_osendmsg
// compat_43_osethostid
// compat_43_osethostname
// compat_43_osetrlimit
// compat_43_osigblock
// compat_43_osigsetmask
// compat_43_osigstack
// compat_43_osigvec
// compat_43_otruncate
// compat_43_owait
// compat_43_stat43
// execve
// extattr_delete_fd
// extattr_delete_file
// extattr_delete_link
// extattr_get_fd
// extattr_get_file
// extattr_get_link
// extattr_list_fd
// extattr_list_file
// extattr_list_link
// extattr_set_fd
// extattr_set_file
// extattr_set_link
// extattrctl
// fchroot
// fdatasync
// fgetxattr
// fktrace
// flistxattr
// fork
// fremovexattr
// fsetxattr
// fstatvfs1
// fsync_range
// getcontext
// getitimer
// getvfsstat
// getxattr
// ioctl
// ktrace
// lchflags
// lchmod
// lfs_bmapv
// lfs_markv
// lfs_segclean
// lfs_segwait
// lgetxattr
// lio_listio
// listxattr
// llistxattr
// lremovexattr
// lseek
// lsetxattr
// lutimes
// madvise
// mincore
// minherit
// modctl
// mq_close
// mq_getattr
// mq_notify
// mq_open
// mq_receive
// mq_send
// mq_setattr
// mq_timedreceive
// mq_timedsend
// mq_unlink
// mremap
// msgget
// msgrcv
// msgsnd
// nfssvc
// ntp_adjtime
// pmc_control
// pmc_get_info
// pollts
// preadv
// profil
// pselect
// pset_assign
// pset_create
// pset_destroy
// ptrace
// pwritev
// quotactl
// rasctl
// readv
// reboot
// removexattr
// sa_enable
// sa_preempt
// sa_register
// sa_setconcurrency
// sa_stacks
// sa_yield
// sbrk
// sched_yield
// semconfig
// semget
// semop
// setcontext
// setitimer
// setxattr
// shmat
// shmdt
// shmget
// sstk
// statvfs1
// swapctl
// sysarch
// syscall
// timer_create
// timer_delete
// timer_getoverrun
// timer_gettime
// timer_settime
// undelete
// utrace
// uuidgen
// vadvise
// vfork
// writev

{'repo_name': 'micahhausler/k8s-oidc-helper', 'stars': '175', 'repo_language': 'Go', 'file_name': 'client_secret.json', 'mime_type': 'text/plain', 'hash': -2072373091569953260, 'source_dataset': 'data'}


/*
 * _CPPopoverWindowView.j
 * AppKit
 *
 * Created by Antoine Mercadal
 * Copyright 2011 <primalmotion@archipelproject.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

@import <Foundation/CPGeometry.j>

@import "CGGeometry.j"
@import "CGGradient.j"
@import "_CPWindowView.j"

var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10);

/*!
    @ignore

    A custom CPWindowView that manages a border and cursor
*/
@implementation _CPPopoverWindowView : _CPWindowView
{
    float       _arrowOffsetX   @accessors(property=arrowOffsetX);
    float       _arrowOffsetY   @accessors(property=arrowOffsetY);
    unsigned    _preferredEdge  @accessors(property=preferredEdge);

    CGSize      _cursorSize;
}

+ (CPString)defaultThemeClass
{
    return @"popover-window-view";
}

+ (CPDictionary)themeAttributes
{
    return @{
            @"background-gradient": [CPNull null],
            @"background-gradient-hud": [CPNull null],
            @"stroke-color": [CPNull null],
            @"stroke-color-hud": [CPNull null],
            @"border-radius": 5.0,
            @"stroke-width": 1.0,
            @"shadow-size": CGSizeMake(0, 6),
            @"shadow-blur": 15.0
        };
}

/*!
    Compute the contentView frame from a given window frame

    @param aFrameRect the window frame
*/
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
    var contentRect = CGRectMakeCopy(aFrameRect),
        modifierX = 16,
        modifierY = 19;

    // @todo change border art and remove this pixel perfect adaptation
    //
    // @comment: If we use this, each time we open the popover, the content
    // view is reduced a little over and over
    // return CGRectInset(contentRect, modifierX, modifierY);

    contentRect.origin.x += modifierX;
    contentRect.origin.y += modifierY;
    contentRect.size.width -= modifierX * 2;
    contentRect.size.height -= modifierY * 2;

    return contentRect;
}

/*!
    Compute the window frame from a given contentView frame

    @param aContentRect the contentView frame
*/
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
    var frameRect = CGRectMakeCopy(aContentRect),
        modifierX = 16,
        modifierY = 19;

    // @todo change border art and remove this pixel perfect adaptation
    // @comment: If we use this, each time we open the popover, the content
    //
    // view is reduced a little over and over
    // return CGRectOffset(frameRect, modifierX, modifierY);

    frameRect.origin.x -= modifierX;
    frameRect.origin.y -= modifierY;
    frameRect.size.width += modifierX * 2;
    frameRect.size.height += modifierY * 2;

    return frameRect;
}

/*!
    Initialize the _CPWindowView
*/
- (id)initWithFrame:(CGRect)aFrame styleMask:(unsigned)aStyleMask
{
    if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
    {
        _arrowOffsetX = 0.0;
        _arrowOffsetY = 0.0;
        _appearance = [CPAppearance appearanceNamed:CPAppearanceNameVibrantLight];
        _cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
    }

    return self;
}

/*!
    Hide the cursor
*/
- (void)hideCursor
{
    _cursorSize = CGSizeMakeZero();
    [self setNeedsDisplay:YES];
}

/*!
    Show the cursor
*/
- (void)showCursor
{
    _cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
    [self setNeedsDisplay:YES];
}

/*!
    Draw the view
*/
- (void)drawRect:(CGRect)aRect
{
    [super drawRect:aRect];

    var context = [[CPGraphicsContext currentContext] graphicsPort],
        radius = [self valueForThemeAttribute:@"border-radius"],
        arrowWidth = _cursorSize.width,
        arrowHeight = _cursorSize.height,
        strokeWidth = [self valueForThemeAttribute:@"stroke-width"],
        halfStrokeWidth = strokeWidth / 2.0,
        strokeColor,
        shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.2],
        shadowSize = [self valueForThemeAttribute:@"shadow-size"],
        shadowBlur = [self valueForThemeAttribute:@"shadow-blur"],
        gradient,
        frame = [self bounds];

    if ([_appearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]])
    {
        gradient = [self valueForThemeAttribute:@"background-gradient"];
        strokeColor = [self valueForThemeAttribute:@"stroke-color"];
    }
    else
    {
        gradient = [self valueForThemeAttribute:@"background-gradient-hud"];
        strokeColor = [self valueForThemeAttribute:@"stroke-color-hud"];
    }

    // fix rect to take care of stroke and shadow
    frame.origin.x += halfStrokeWidth + shadowBlur;
    frame.origin.y += halfStrokeWidth + (shadowBlur + shadowSize.height / 2);
    frame.size.width -= strokeWidth + (shadowBlur * 2);
    frame.size.height -= strokeWidth + (shadowBlur * 2 + shadowSize.height);

    CGContextSetStrokeColor(context, strokeColor);
    CGContextSetLineWidth(context, strokeWidth);

    CGContextBeginPath(context);
    CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor);
    CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX(frame), 0.0), CGPointMake(CGRectGetMidX(frame), frame.size.height), 0);

    var xMin = CGRectGetMinX(frame),
        xMax = CGRectGetMaxX(frame),
        yMin = CGRectGetMinY(frame),
        yMax = CGRectGetMaxY(frame),
        arrowMinX = CGAlignCoordinate(xMin + radius + strokeWidth),
        arrowMaxX = CGAlignCoordinate(xMax - radius - strokeWidth),
        arrowMinY = CGAlignCoordinate(yMin + radius + strokeWidth),
        arrowMaxY = CGAlignCoordinate(yMax - radius + strokeWidth),
        arrowAnchor = CGPointMakeZero(),
        arrowStart = CGPointMakeZero(),
        pt = CGPointMakeZero();

    // draw!
    var path = CGPathCreateMutable();

    switch (_preferredEdge)
    {
        case CPMinXEdge:
        case CPMaxXEdge:
            // origin nw
            pt.x = CGAlignCoordinate(xMin + radius);
            pt.y = yMin;
            CGPathMoveToPoint(path, NULL, pt.x, pt.y);

            // ne
            pt.x = CGAlignCoordinate(xMax - radius);
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, xMax, yMin, xMax, CGAlignCoordinate(yMin + radius));

            if (_preferredEdge === CPMinXEdge)
            {
                // arrow CPMinXEdge
                arrowAnchor.x = CGAlignStroke(xMax, strokeWidth);
                arrowAnchor.y = CGAlignCoordinate((frame.size.height / 2) + yMin + _arrowOffsetY);

                // to top edge
                pt.y = CGAlignCoordinate(arrowAnchor.y - (arrowWidth / 2));

                // adjust starting point to not go beyond the corner
                if (pt.y <= arrowMinY)
                    pt.y = arrowMinY;
                else if ((pt.y + arrowWidth) > arrowMaxY)
                    pt.y = arrowMaxY - arrowWidth;

                pt.x = arrowAnchor.x;
                arrowStart = CGPointMakeCopy(pt);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // top edge -> point
                pt.x = CGAlignStroke(arrowAnchor.x + arrowHeight, strokeWidth);
                pt.y = arrowAnchor.y;
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // point -> bottom edge
                pt.x = arrowAnchor.x;
                pt.y = CGAlignCoordinate(arrowStart.y + arrowWidth);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            }

            // se
            pt.x = xMax;
            pt.y = CGAlignCoordinate(yMax - radius);
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, pt.x, yMax, CGAlignCoordinate(xMax - radius), yMax);

            // sw
            pt.x = CGAlignCoordinate(xMin + radius);
            pt.y = yMax;
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, xMin, pt.y, xMin, CGAlignCoordinate(yMax - radius));

            if (_preferredEdge === CPMaxXEdge)
            {
                // arrow CPMaxXEdge
                arrowAnchor.x = CGAlignStroke(xMin, strokeWidth);
                arrowAnchor.y = CGAlignCoordinate((frame.size.height / 2) + yMin + _arrowOffsetY);

                // to bottom edge
                pt.y = CGAlignCoordinate(arrowAnchor.y + (arrowWidth / 2));

                // adjust starting point to not go beyond the corner
                if ((pt.y - arrowWidth) < arrowMinY)
                    pt.y = arrowMinY + arrowWidth;
                else if (pt.y > arrowMaxY)
                    pt.y = arrowMaxY;

                pt.x = arrowAnchor.x;
                arrowStart = CGPointMakeCopy(pt);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // bottom edge -> point
                pt.x = CGAlignStroke(arrowAnchor.x - arrowHeight, strokeWidth);
                pt.y = arrowAnchor.y;
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // point -> top edge
                pt.x = arrowAnchor.x;
                pt.y = CGAlignCoordinate(arrowStart.y - arrowWidth);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            }

            // nw
            pt.x = xMin;
            pt.y = CGAlignCoordinate(yMin + radius);
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, pt.x, yMin, CGAlignCoordinate(xMin + radius), yMin);
            break;

        case CPMaxYEdge:
        case CPMinYEdge:
            // origin sw
            pt.x = xMin;
            pt.y = CGAlignCoordinate(yMax - radius);
            CGPathMoveToPoint(path, NULL, pt.x, pt.y);

            // nw
            pt.y = CGAlignCoordinate(yMin + radius);
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, pt.x, yMin, CGAlignCoordinate(xMin + radius), yMin);

            if (_preferredEdge === CPMaxYEdge)
            {
                // arrow CPMaxYEdge
                arrowAnchor.x = CGAlignCoordinate((frame.size.width / 2) + xMin + _arrowOffsetX);
                arrowAnchor.y = CGAlignStroke(yMin + _arrowOffsetY, strokeWidth);

                // to left edge
                pt.x = CGAlignCoordinate(arrowAnchor.x - (arrowWidth / 2));

                // adjust starting point to not go beyond the corner
                if (pt.x < arrowMinX)
                    pt.x = arrowMinX;
                else if ((pt.x + arrowWidth) > arrowMaxX)
                    pt.x = arrowMaxX - arrowWidth;

                pt.y = arrowAnchor.y;
                arrowStart = CGPointMakeCopy(pt);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // left edge -> point
                pt.x = arrowAnchor.x;
                pt.y = CGAlignStroke(arrowAnchor.y - arrowHeight, strokeWidth);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // point -> right edge
                pt.x = CGAlignCoordinate(arrowStart.x + arrowWidth);
                pt.y = arrowAnchor.y;
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            }

            // ne
            pt.x = CGAlignCoordinate(xMax - radius);
            pt.y = yMin;
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, xMax, pt.y, xMax, CGAlignCoordinate(yMin + radius));

            // se
            pt.x = xMax;
            pt.y = CGAlignCoordinate(yMax - radius);
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, pt.x, yMax, CGAlignCoordinate(xMax - radius), yMax);

            if (_preferredEdge === CPMinYEdge)
            {
                // arrow CPMinYEdge
                arrowAnchor.x = CGAlignCoordinate((frame.size.width / 2) + xMin + _arrowOffsetX);
                arrowAnchor.y = CGAlignStroke(yMax + _arrowOffsetY, strokeWidth);

                // to right edge
                pt.x = CGAlignCoordinate(arrowAnchor.x + (arrowWidth / 2));

                // adjust starting point to not go beyond the corner
                if ((pt.x - arrowWidth) < arrowMinX)
                    pt.x = arrowMinX + arrowWidth;
                else if (pt.x > arrowMaxX)
                    pt.x = arrowMaxX;

                pt.y = arrowAnchor.y;
                arrowStart = CGPointMakeCopy(pt);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // right edge -> point
                pt.x = arrowAnchor.x;
                pt.y = CGAlignStroke(arrowAnchor.y + arrowHeight, strokeWidth);
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);

                // point -> left edge
                pt.x = CGAlignCoordinate(arrowStart.x - arrowWidth);
                pt.y = arrowAnchor.y;
                CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            }

            // sw
            pt.x = CGAlignCoordinate(xMin + radius);
            pt.y = yMax;
            CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
            CGPathAddCurveToPoint(path, NULL, pt.x, pt.y, xMin, pt.y, xMin, CGAlignCoordinate(yMax - radius));
            break;

        default:
            // no computed edge means standard rounded rect
            CGPathAddPath(path, NULL, CGPathWithRoundedRectangleInRect(frame, radius, radius, YES, YES, YES, YES));
    }

    CGContextAddPath(context, path);
    CGContextStrokePath(context);

    CGContextAddPath(context, path);
    CGContextFillPath(context);
}

@end

{'repo_name': 'cappuccino/cappuccino', 'stars': '2168', 'repo_language': 'Objective-J', 'file_name': 'Info.plist', 'mime_type': 'text/xml', 'hash': -8664502255198523473, 'source_dataset': 'data'}


// ----------------------------------------------------------------------- //
//
// MODULE  : AISensorNodeStalk.cpp
//
// PURPOSE :
//
// CREATED : 5/17/04
//
// (c) 2004 Monolith Productions, Inc.  All Rights Reserved
// ----------------------------------------------------------------------- //

#include "Stdafx.h"
#include "AISensorNodeStalk.h"
#include "AINodeMgr.h"
#include "AIDB.h"
#include "AI.h"

DEFINE_AI_FACTORY_CLASS_SPECIFIC( Sensor, CAISensorNodeStalk, kSensor_NodeStalk );

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CAISensorNodeStalk::Con/destructor
//
//	PURPOSE:	Factory required default constructor/destructor
//
// ----------------------------------------------------------------------- //

CAISensorNodeStalk::CAISensorNodeStalk()
{
}

CAISensorNodeStalk::~CAISensorNodeStalk()
{
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CAISensorNodeStalk::SearchForNodes
//
//	PURPOSE:	Generate a list of potentially valid nodes.
//
// ----------------------------------------------------------------------- //

void CAISensorNodeStalk::SearchForNodes( AIVALID_NODE_LIST& lstValidNodes )
{
	SAIVALIDATE_NODE ValidateNodeStruct;
	ValidateNodeStruct.pAI = m_pAI;
	ValidateNodeStruct.vPos = m_pAI->GetPosition();
	ValidateNodeStruct.fSearchMult = m_fSearchMult;
	ValidateNodeStruct.dwPotentialFlags = kNodePotential_RadiusOrRegion;

	g_pAINodeMgr->FindPotentiallyValidNodes( m_pSensorRecord->eNodeType, lstValidNodes, ValidateNodeStruct );
}

{'repo_name': 'jsj2008/lithtech', 'stars': '126', 'repo_language': 'C++', 'file_name': 'vs_powershield1.vsh', 'mime_type': 'text/plain', 'hash': 3937960886258766289, 'source_dataset': 'data'}


Template spins up a Deis cluster.

Summary: Deis cluster

{'repo_name': 'Azure/azure-quickstart-templates', 'stars': '7645', 'repo_language': 'PowerShell', 'file_name': 'azuredeploy.json', 'mime_type': 'text/plain', 'hash': -8472455044456540753, 'source_dataset': 'data'}


collision with address that has been selfdestructed in the same transaction but then REVERT is called

{'repo_name': 'status-im/nimbus', 'stars': '356', 'repo_language': 'Nim', 'file_name': 'nim.nix', 'mime_type': 'text/plain', 'hash': -2459551006588651351, 'source_dataset': 'data'}


// STLport regression testsuite component.
// To compile as a separate example, please #define MAIN.

#include <algorithm>
#include <iostream>

#ifdef MAIN
#define setdiff0_test main
#endif

#if !defined (STLPORT) || defined(__STL_USE_NAMESPACES)
using namespace std;
#endif
int setdiff0_test(int, char**)
{
  cout<<"Results of setdiff0_test:"<<endl;
int v1[3] = { 13, 18, 23 };
int v2[4] = { 10, 13, 17, 23 };
int result[4] = { 0, 0, 0, 0 };

  set_difference((int*)v1, (int*)v1 + 3, (int*)v2, (int*)v2 + 4, (int*)result);
  int i;
  for(i = 0; i < 4; i++)
    cout << result[i] << ' ';
  cout << endl;
  set_difference((int*)v2, (int*)v2 + 4, (int*)v1, (int*)v1 + 2, (int*)result);
  for(i = 0; i < 4; i++)
    cout << result[i] << ' ';
  cout << endl;
  return 0;
}

{'repo_name': 'unknownworlds/NS', 'stars': '220', 'repo_language': 'C++', 'file_name': 'steam installer.iss', 'mime_type': 'text/plain', 'hash': 8216408130236906796, 'source_dataset': 'data'}


/*
  Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.

  The MySQL Connector/J is licensed under the terms of the GPL,
  like most MySQL Connectors. There are special exceptions to the
  terms and conditions of the GPL as it is applied to this software,
  see the FLOSS License Exception available on mysql.com.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; version 2 of the
  License.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  02110-1301 USA

 */
package com.mysql.jdbc;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * An implementation of java.sql.Connection that load balances requests across a
 * series of MySQL JDBC connections, where the balancing takes place at
 * transaction commit.
 *
 * Therefore, for this to work (at all), you must use transactions, even if only
 * reading data.
 *
 * This implementation will invalidate connections that it detects have had
 * communication errors when processing a request. Problematic hosts will be
 * added to a global blacklist for loadBalanceBlacklistTimeout ms, after which
 * they will be removed from the blacklist and made eligible once again to be
 * selected for new connections.
 *
 * This implementation is thread-safe, but it's questionable whether sharing a
 * connection instance amongst threads is a good idea, given that transactions
 * are scoped to connections in JDBC.
 *
 * @version $Id: $
 *
 */
public class LoadBalancingConnectionProxy implements InvocationHandler,
		PingTarget {

	private static Method getLocalTimeMethod;

	private long totalPhysicalConnections = 0;
	private long activePhysicalConnections = 0;
	private String hostToRemove = null;
	private long lastUsed = 0;
	private long transactionCount = 0;
	private ConnectionGroup connectionGroup = null;

	public static final String BLACKLIST_TIMEOUT_PROPERTY_KEY = "loadBalanceBlacklistTimeout";

	static {
		try {
			getLocalTimeMethod = System.class.getMethod("nanoTime",
					new Class[0]);
		} catch (SecurityException e) {
			// ignore
		} catch (NoSuchMethodException e) {
			// ignore
		}
	}

	// Lifted from C/J 5.1's JDBC-2.0 connection pool classes, let's merge this
	// if/when this gets into 5.1
	protected class ConnectionErrorFiringInvocationHandler implements
			InvocationHandler {
		Object invokeOn = null;

		public ConnectionErrorFiringInvocationHandler(Object toInvokeOn) {
			invokeOn = toInvokeOn;
		}

		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			Object result = null;

			try {
				result = method.invoke(invokeOn, args);

				if (result != null) {
					result = proxyIfInterfaceIsJdbc(result, result.getClass());
				}
			} catch (InvocationTargetException e) {
				dealWithInvocationException(e);
			}

			return result;
		}
	}

	protected MySQLConnection currentConn;

	protected List<String> hostList;

	protected Map<String, ConnectionImpl> liveConnections;

	private Map<ConnectionImpl, String> connectionsToHostsMap;

	private long[] responseTimes;

	private Map<String, Integer> hostsToListIndexMap;

	private boolean inTransaction = false;

	private long transactionStartTime = 0;

	private Properties localProps;

	private boolean isClosed = false;

	private BalanceStrategy balancer;

	private int retriesAllDown;

	private static Map<String, Long> globalBlacklist = new HashMap<String, Long>();

	private int globalBlacklistTimeout = 0;

	private long connectionGroupProxyID = 0;

	private LoadBalanceExceptionChecker exceptionChecker;

	private Map<Class, Boolean> jdbcInterfacesForProxyCache = new HashMap<Class, Boolean>();

	private MySQLConnection thisAsConnection = null;

	/**
	 * Creates a proxy for java.sql.Connection that routes requests between the
	 * given list of host:port and uses the given properties when creating
	 * connections.
	 *
	 * @param hosts
	 * @param props
	 * @throws SQLException
	 */
	LoadBalancingConnectionProxy(List<String> hosts, Properties props)
			throws SQLException {
		String group = props.getProperty("loadBalanceConnectionGroup",
				null);
		boolean enableJMX = false;
		String enableJMXAsString = props.getProperty("loadBalanceEnableJMX",
				"false");
		try{
			enableJMX = Boolean.parseBoolean(enableJMXAsString);
		} catch (Exception e){
			throw SQLError.createSQLException(Messages.getString(
					"LoadBalancingConnectionProxy.badValueForLoadBalanceEnableJMX",
					new Object[] { enableJMXAsString }),
					SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
		}

		if(group != null){
			this.connectionGroup = ConnectionGroupManager.getConnectionGroupInstance(group);
			if(enableJMX){
				ConnectionGroupManager.registerJmx();
			}
			this.connectionGroupProxyID = this.connectionGroup.registerConnectionProxy(this, hosts);
			hosts = new ArrayList<String>(this.connectionGroup.getInitialHosts());
		}

		this.hostList = hosts;

		int numHosts = this.hostList.size();

		this.liveConnections = new HashMap<String, ConnectionImpl>(numHosts);
		this.connectionsToHostsMap = new HashMap<ConnectionImpl, String>(numHosts);
		this.responseTimes = new long[numHosts];
		this.hostsToListIndexMap = new HashMap<String, Integer>(numHosts);

		this.localProps = (Properties) props.clone();
		this.localProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY);
		this.localProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY);

		for (int i = 0; i < numHosts; i++) {
			this.hostsToListIndexMap.put(this.hostList.get(i), new Integer(i));
			this.localProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY + "."
					+ (i + 1));
			this.localProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY + "."
					+ (i + 1));
		}

		this.localProps.remove(NonRegisteringDriver.NUM_HOSTS_PROPERTY_KEY);
		this.localProps.setProperty("useLocalSessionState", "true");

		String strategy = this.localProps.getProperty("loadBalanceStrategy",
				"random");

		String lbExceptionChecker = this.localProps.getProperty("loadBalanceExceptionChecker",
		"com.mysql.jdbc.StandardLoadBalanceExceptionChecker");

		String retriesAllDownAsString = this.localProps.getProperty(
				"retriesAllDown", "120");

		try {
			this.retriesAllDown = Integer.parseInt(retriesAllDownAsString);
		} catch (NumberFormatException nfe) {
			throw SQLError.createSQLException(Messages.getString(
					"LoadBalancingConnectionProxy.badValueForRetriesAllDown",
					new Object[] { retriesAllDownAsString }),
					SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
		}
		String blacklistTimeoutAsString = this.localProps.getProperty(
				BLACKLIST_TIMEOUT_PROPERTY_KEY, "0");

		try {
			this.globalBlacklistTimeout = Integer
					.parseInt(blacklistTimeoutAsString);
		} catch (NumberFormatException nfe) {
			throw SQLError
					.createSQLException(
							Messages
									.getString(
											"LoadBalancingConnectionProxy.badValueForLoadBalanceBlacklistTimeout",
											new Object[] { retriesAllDownAsString }),
							SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null);
		}

		if ("random".equals(strategy)) {
			this.balancer = (BalanceStrategy) Util.loadExtensions(null, props,
					"com.mysql.jdbc.RandomBalanceStrategy",
					"InvalidLoadBalanceStrategy", null).get(0);
		} else if ("bestResponseTime".equals(strategy)) {
			this.balancer = (BalanceStrategy) Util.loadExtensions(null, props,
					"com.mysql.jdbc.BestResponseTimeBalanceStrategy",
					"InvalidLoadBalanceStrategy", null).get(0);
		} else {
			this.balancer = (BalanceStrategy) Util.loadExtensions(null, props,
					strategy, "InvalidLoadBalanceStrategy", null).get(0);
		}

		this.balancer.init(null, props);

		this.exceptionChecker = (LoadBalanceExceptionChecker) Util.loadExtensions(null, props,
				lbExceptionChecker, "InvalidLoadBalanceExceptionChecker", null).get(0);
		this.exceptionChecker.init(null, props);

		thisAsConnection = new LoadBalancedMySQLConnection(this);

		pickNewConnection();

	}

	/**
	 * Creates a new physical connection for the given host:port and updates
	 * required internal mappings and statistics for that connection.
	 *
	 * @param hostPortSpec
	 * @return
	 * @throws SQLException
	 */
	public synchronized ConnectionImpl createConnectionForHost(
			String hostPortSpec) throws SQLException {
		Properties connProps = (Properties) this.localProps.clone();

		String[] hostPortPair = NonRegisteringDriver
				.parseHostPortPair(hostPortSpec);
		String hostName = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX];
		String portNumber = hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX];
		String dbName = connProps
				.getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY);

		if (hostName == null) {
			throw new SQLException(
					"Could not find a hostname to start a connection to");
		}
		if (portNumber == null) {
			portNumber = "3306";// use default
		}

		connProps.setProperty(NonRegisteringDriver.HOST_PROPERTY_KEY, hostName);
		connProps.setProperty(NonRegisteringDriver.PORT_PROPERTY_KEY,
				portNumber);
		connProps.setProperty(NonRegisteringDriver.HOST_PROPERTY_KEY + ".1",
				hostName);
		connProps.setProperty(NonRegisteringDriver.PORT_PROPERTY_KEY + ".1",
				portNumber);
		connProps.setProperty(NonRegisteringDriver.NUM_HOSTS_PROPERTY_KEY, "1");
		connProps.setProperty("roundRobinLoadBalance", "false"); // make sure we
																	// don't
																	// pickup
																	// the
																	// default
																	// value

		ConnectionImpl conn = (ConnectionImpl) ConnectionImpl.getInstance(
				hostName, Integer.parseInt(portNumber), connProps, dbName,
				"jdbc:mysql://" + hostName + ":" + portNumber + "/");

		this.liveConnections.put(hostPortSpec, conn);
		this.connectionsToHostsMap.put(conn, hostPortSpec);

		this.activePhysicalConnections++;
		this.totalPhysicalConnections++;

		conn.setProxy(this.thisAsConnection);

		return conn;
	}

	/**
	 * @param e
	 * @throws SQLException
	 * @throws Throwable
	 * @throws InvocationTargetException
	 */
	void dealWithInvocationException(InvocationTargetException e)
			throws SQLException, Throwable, InvocationTargetException {
		Throwable t = e.getTargetException();

		if (t != null) {
			if (t instanceof SQLException && shouldExceptionTriggerFailover((SQLException) t )) {
				invalidateCurrentConnection();
				pickNewConnection();
			}

			throw t;
		}

		throw e;
	}

	/**
	 * Closes current connection and removes it from required mappings.
	 *
	 * @throws SQLException
	 */
	synchronized void invalidateCurrentConnection() throws SQLException {
		try {
			if (!this.currentConn.isClosed()) {
				this.currentConn.close();
			}

		} finally {
			// add host to the global blacklist, if enabled
			if (this.isGlobalBlacklistEnabled()) {
				this.addToGlobalBlacklist(this.connectionsToHostsMap
						.get(this.currentConn));

			}
			// remove from liveConnections
			this.liveConnections.remove(this.connectionsToHostsMap
					.get(this.currentConn));
			Object mappedHost = this.connectionsToHostsMap
					.remove(this.currentConn);
			if (mappedHost != null
					&& this.hostsToListIndexMap.containsKey(mappedHost)) {
				int hostIndex = (this.hostsToListIndexMap
						.get(mappedHost)).intValue();
				// reset the statistics for the host
				synchronized (this.responseTimes) {
					this.responseTimes[hostIndex] = 0;
				}
			}
		}
	}

	private void closeAllConnections() {
		synchronized (this) {
			// close all underlying connections
			Iterator<ConnectionImpl> allConnections = this.liveConnections.values().iterator();

			while (allConnections.hasNext()) {
				try {
					this.activePhysicalConnections--;
					allConnections.next().close();
				} catch (SQLException e) {
				}
			}

			if (!this.isClosed) {
				this.balancer.destroy();
				if(this.connectionGroup != null){
					this.connectionGroup.closeConnectionProxy(this);
				}
			}

			this.liveConnections.clear();
			this.connectionsToHostsMap.clear();
		}

	}

	/**
	 * Proxies method invocation on the java.sql.Connection interface, trapping
	 * "close", "isClosed" and "commit/rollback" (to switch connections for load
	 * balancing).
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {

		String methodName = method.getName();

		if("getLoadBalanceSafeProxy".equals(methodName)){
			return this.currentConn;
		}

		if ("equals".equals(methodName) && args.length == 1) {
			if (args[0] instanceof Proxy) {
				return Boolean.valueOf((((Proxy) args[0]).equals(this)));
			}
			return Boolean.valueOf(this.equals(args[0]));
		}

		if ("hashCode".equals(methodName)) {
			return new Integer(this.hashCode());
		}

		if ("close".equals(methodName)) {
			closeAllConnections();
			this.isClosed = true;
			return null;
		}

		if ("isClosed".equals(methodName)) {
			return Boolean.valueOf(this.isClosed);
		}

		if (this.isClosed) {
			throw SQLError.createSQLException(
					"No operations allowed after connection closed.",
					SQLError.SQL_STATE_CONNECTION_NOT_OPEN, null /*
																 * no access to
																 * a interceptor
																 * here...
																 */);
		}

		if (!inTransaction) {
			this.inTransaction = true;
			this.transactionStartTime = getLocalTimeBestResolution();
			this.transactionCount++;
		}

		Object result = null;

		try {
			this.lastUsed = System.currentTimeMillis();
			result = method.invoke(thisAsConnection, args);

			if (result != null) {
				if (result instanceof com.mysql.jdbc.Statement) {
					((com.mysql.jdbc.Statement) result).setPingTarget(this);
				}

				result = proxyIfInterfaceIsJdbc(result, result.getClass());
			}
		} catch (InvocationTargetException e) {
			dealWithInvocationException(e);
		} finally {
			if ("commit".equals(methodName) || "rollback".equals(methodName)) {
				this.inTransaction = false;

				// Update stats
				String host = this.connectionsToHostsMap.get(this.currentConn);
				// avoid NPE if the connection has already been removed from
				// connectionsToHostsMap
				// in invalidateCurrenctConnection()
				if (host != null) {
					synchronized (this.responseTimes) {
						int hostIndex = (this.hostsToListIndexMap
								.get(host)).intValue();

						if(hostIndex < this.responseTimes.length){
							this.responseTimes[hostIndex] = getLocalTimeBestResolution()
									- this.transactionStartTime;
						}
					}
				}
				pickNewConnection();
			}
		}

		return result;
	}

	/**
	 * Picks the "best" connection to use for the next transaction based on the
	 * BalanceStrategy in use.
	 *
	 * @throws SQLException
	 */
	protected synchronized void pickNewConnection() throws SQLException {
		if (this.currentConn == null) { // startup
			this.currentConn = this.balancer.pickConnection(this, Collections
					.unmodifiableList(this.hostList), Collections
					.unmodifiableMap(this.liveConnections),
					this.responseTimes.clone(), this.retriesAllDown);
			return;
		}

		if(this.currentConn.isClosed()){
			invalidateCurrentConnection();
		}

		boolean currentAutoCommit = this.currentConn.getAutoCommit();
		int currentTransIsolation = this.currentConn.getTransactionIsolation();
		int pingTimeout = this.currentConn.getLoadBalancePingTimeout();
		boolean pingBeforeReturn = this.currentConn.getLoadBalanceValidateConnectionOnSwapServer();
		for(int hostsTried = 0, hostsToTry = this.hostList.size(); hostsTried <= hostsToTry; hostsTried++){
			try{
				ConnectionImpl newConn = this.balancer.pickConnection(

					this, Collections.unmodifiableList(this.hostList), Collections
							.unmodifiableMap(this.liveConnections),
					this.responseTimes.clone(), this.retriesAllDown);

				if (this.currentConn != null) {
					if(pingBeforeReturn){
						if(pingTimeout == 0){
							newConn.ping();
						} else {
							newConn.pingInternal(true, pingTimeout);
						}
					}
					newConn.setTransactionIsolation(currentTransIsolation);
					newConn.setAutoCommit(currentAutoCommit);
				}

				this.currentConn = newConn;
				return;
			} catch (SQLException e){

				if (shouldExceptionTriggerFailover(e)) {
					// connection error, close up shop on current
					// connection
					invalidateCurrentConnection();
				}
			}

		}
		// no hosts available to swap connection to, close up.
		this.isClosed = true;
	}

	/**
	 * Recursively checks for interfaces on the given object to determine if it
	 * implements a java.sql interface, and if so, proxies the instance so that
	 * we can catch and fire SQL errors.
	 *
	 * @param toProxy
	 * @param clazz
	 * @return
	 */
	Object proxyIfInterfaceIsJdbc(Object toProxy, Class clazz) {

		if(isInterfaceJdbc(clazz)){

		Class[] interfacesToProxy = getAllInterfacesToProxy(clazz);

		return Proxy.newProxyInstance(toProxy.getClass()
				.getClassLoader(), interfacesToProxy,
				createConnectionProxy(toProxy));
		}

		return toProxy;
	}

	private Map<Class, Class[]> allInterfacesToProxy = new HashMap<Class, Class[]>();

	private Class[] getAllInterfacesToProxy(Class clazz) {
		Class[] interfacesToProxy = (Class[]) this.allInterfacesToProxy.get(clazz);

		if (interfacesToProxy != null) {
			return interfacesToProxy;
		}

		List<Class> interfaces = new LinkedList<Class>();

		Class superClass = clazz;

		while (!(superClass.equals(Object.class))) {
			Class[] declared = superClass.getInterfaces();

			for (int i = 0; i < declared.length; i++) {
				interfaces.add(declared[i]);
			}

			superClass = superClass.getSuperclass();
		}

		interfacesToProxy = new Class[interfaces.size()];
		interfaces.toArray(interfacesToProxy);

		this.allInterfacesToProxy.put(clazz, interfacesToProxy);

		return interfacesToProxy;
	}

	private boolean isInterfaceJdbc(Class clazz){
		if(this.jdbcInterfacesForProxyCache.containsKey(clazz)){
			return (this.jdbcInterfacesForProxyCache.get(clazz)).booleanValue();
		}

		Class[] interfaces = clazz.getInterfaces();

		for (int i = 0; i < interfaces.length; i++) {
			String packageName = interfaces[i].getPackage().getName();

			if ("java.sql".equals(packageName)
					|| "javax.sql".equals(packageName)
					|| "com.mysql.jdbc".equals(packageName)) {
				this.jdbcInterfacesForProxyCache.put(clazz, new Boolean(true));
				return true;
			}

			if(isInterfaceJdbc(interfaces[i])){
				this.jdbcInterfacesForProxyCache.put(clazz, new Boolean(true));
				return true;
			}
		}

		this.jdbcInterfacesForProxyCache.put(clazz, new Boolean(false));
		return false;

	}

	protected ConnectionErrorFiringInvocationHandler createConnectionProxy(
			Object toProxy) {
		return new ConnectionErrorFiringInvocationHandler(toProxy);
	}

	/**
	 * Returns best-resolution representation of local time, using nanoTime() if
	 * available, otherwise defaulting to currentTimeMillis().
	 */
	private static long getLocalTimeBestResolution() {
		if (getLocalTimeMethod != null) {
			try {
				return ((Long) getLocalTimeMethod.invoke(null, (Object[])null))
						.longValue();
			} catch (IllegalArgumentException e) {
				// ignore - we fall through to currentTimeMillis()
			} catch (IllegalAccessException e) {
				// ignore - we fall through to currentTimeMillis()
			} catch (InvocationTargetException e) {
				// ignore - we fall through to currentTimeMillis()
			}
		}

		return System.currentTimeMillis();
	}

	public synchronized void doPing() throws SQLException {
		SQLException se = null;
		boolean foundHost = false;
		int pingTimeout = this.currentConn.getLoadBalancePingTimeout();
		synchronized (this) {
			for (Iterator<String> i = this.hostList.iterator(); i.hasNext();) {
				String host = i.next();
				ConnectionImpl conn = this.liveConnections.get(host);
				if (conn == null) {
					continue;
				}
				try {
					if(pingTimeout == 0){
						conn.ping();
					} else {
						conn.pingInternal(true, pingTimeout);
					}
					foundHost = true;
				} catch (SQLException e) {
					this.activePhysicalConnections--;
					// give up if it is the current connection, otherwise NPE
					// faking resultset later.
					if (host.equals(this.connectionsToHostsMap
							.get(this.currentConn))) {
						// clean up underlying connections, since connection
						// pool won't do it
						closeAllConnections();
						this.isClosed = true;
						throw e;
					}

					// if the Exception is caused by ping connection lifetime
					// checks, don't add to blacklist
					if (e
							.getMessage()
							.equals(
									Messages
											.getString("Connection.exceededConnectionLifetime"))) {
						// only set the return Exception if it's null
						if (se == null) {
							se = e;
						}
					} else {
						// overwrite the return Exception no matter what
						se = e;
						if (this.isGlobalBlacklistEnabled()) {
							this.addToGlobalBlacklist(host);
						}
					}
					// take the connection out of the liveConnections Map
					this.liveConnections.remove(this.connectionsToHostsMap
							.get(conn));
				}
			}
		}
		// if there were no successful pings
		if (!foundHost) {
			closeAllConnections();
			this.isClosed = true;
			// throw the stored Exception, if exists
			if (se != null) {
				throw se;
			}
			// or create a new SQLException and throw it, must be no
			// liveConnections
			((ConnectionImpl) this.currentConn)
					.throwConnectionClosedException();
		}
	}

	public void addToGlobalBlacklist(String host, long timeout) {
		if (this.isGlobalBlacklistEnabled()) {
			synchronized (globalBlacklist) {
				globalBlacklist.put(host, new Long(timeout));
			}
		}
	}

	public void addToGlobalBlacklist(String host){
		addToGlobalBlacklist(host, System.currentTimeMillis()
						+ this.globalBlacklistTimeout);

	}

	public boolean isGlobalBlacklistEnabled() {
		return (this.globalBlacklistTimeout > 0);
	}

	public Map<String, Long> getGlobalBlacklist() {
		if (!this.isGlobalBlacklistEnabled()) {
			String localHostToRemove = this.hostToRemove;
			if(hostToRemove != null){
				HashMap<String, Long> fakedBlacklist = new HashMap<String, Long>();
				fakedBlacklist.put(localHostToRemove, new Long(System.currentTimeMillis() + 5000));
				return fakedBlacklist;
			}
			return new HashMap<String, Long>(1);
		}

		// Make a local copy of the blacklist
		Map<String, Long> blacklistClone = new HashMap<String, Long>(globalBlacklist.size());
		// Copy everything from synchronized global blacklist to local copy for
		// manipulation
		synchronized (globalBlacklist) {
			blacklistClone.putAll(globalBlacklist);
		}
		Set<String> keys = blacklistClone.keySet();

		// we're only interested in blacklisted hosts that are in the hostList
		keys.retainAll(this.hostList);
		if (keys.size() == this.hostList.size()) {
			// return an empty blacklist, let the BalanceStrategy
			// implementations try to connect to everything
			// since it appears that all hosts are unavailable - we don't want
			// to wait for
			// loadBalanceBlacklistTimeout to expire.
			return new HashMap<String, Long>(1);
		}

		// Don't need to synchronize here as we using a local copy
		for (Iterator<String> i = keys.iterator(); i.hasNext();) {
			String host = i.next();
			// OK if null is returned because another thread already purged Map
			// entry.
			Long timeout = globalBlacklist.get(host);
			if (timeout != null
					&& timeout.longValue() < System.currentTimeMillis()) {
				// Timeout has expired, remove from blacklist
				synchronized (globalBlacklist) {
					globalBlacklist.remove(host);
				}
				i.remove();
			}

		}

		return blacklistClone;
	}

	public boolean shouldExceptionTriggerFailover(SQLException ex){
		return this.exceptionChecker.shouldExceptionTriggerFailover(ex);

	}

	public void removeHostWhenNotInUse(String host) throws SQLException {
		int timeBetweenChecks = 1000;
		long timeBeforeHardFail = 15000;
		addToGlobalBlacklist(host, timeBeforeHardFail + 1000);
		long cur = System.currentTimeMillis();
		while(System.currentTimeMillis() - timeBeforeHardFail < cur){
			synchronized (this){
				this.hostToRemove = host;
				if(!host.equals(this.currentConn.getHost())){
					removeHost(host);
					return;
				}
			}
			try {
				Thread.sleep(timeBetweenChecks);
			} catch (InterruptedException e) {
				// better to swallow this and retry.
			}

		}
		removeHost(host);
	}

	public void removeHost(String host) throws SQLException {
		synchronized(this){
			if(this.connectionGroup != null){
				if(this.connectionGroup.getInitialHosts().size() == 1 && this.connectionGroup.getInitialHosts().contains(host)){
					throw SQLError.createSQLException("Cannot remove only configured host.", null);
				}
			}
			this.hostToRemove = host;
			if(host.equals(this.currentConn.getHost())){
				closeAllConnections();
			} else {
				this.connectionsToHostsMap.remove(this.liveConnections.remove(host));
				Integer idx = this.hostsToListIndexMap.remove(host);
				long[] newResponseTimes = new long[this.responseTimes.length - 1];
				int newIdx = 0;
				for(Iterator<String> i = this.hostList.iterator(); i.hasNext(); newIdx++){
					String copyHost = i.next();
					if(idx != null && idx.intValue() < this.responseTimes.length){
						newResponseTimes[newIdx] = this.responseTimes[idx.intValue()];
						this.hostsToListIndexMap.put(copyHost, new Integer(newIdx));
					}
				}
				this.responseTimes = newResponseTimes;
			}
		}

	}

	public synchronized boolean addHost(String host){
		synchronized(this){
			if(this.hostsToListIndexMap.containsKey(host)){
				return false;
			}
			long[] newResponseTimes = new long[this.responseTimes.length + 1];
			for(int i = 0; i < this.responseTimes.length; i++){
				newResponseTimes[i] = this.responseTimes[i];
			}
			this.responseTimes = newResponseTimes;
			this.hostList.add(host);
			this.hostsToListIndexMap.put(host, new Integer(this.responseTimes.length - 1));
		}
		return true;
	}

	public long getLastUsed(){
		return this.lastUsed;
	}

	public boolean inTransaction(){
		return this.inTransaction;
	}

	public long getTransactionCount(){
		return this.transactionCount;
	}

	public long getActivePhysicalConnectionCount(){
		return this.activePhysicalConnections;
	}
	public long getTotalPhysicalConnectionCount(){
		return this.totalPhysicalConnections;
	}

	public long getConnectionGroupProxyID(){
		return this.connectionGroupProxyID;
	}

	public String getCurrentActiveHost() {
		MySQLConnection c = this.currentConn;
		if(c != null){
			Object o = this.connectionsToHostsMap.get(c);
			if(o != null){
				return o.toString();
			}
		}
		return null;
	}

	public long getCurrentTransactionDuration(){
		long st = 0;
		if(this.inTransaction && (st = this.transactionStartTime) > 0){
			return getLocalTimeBestResolution() - this.transactionStartTime;
		}
		return 0;
	}

}

{'repo_name': 'codefollower/Open-Source-Research', 'stars': '197', 'repo_language': 'C++', 'file_name': 'SimpleExample.java', 'mime_type': 'text/x-java', 'hash': 3461650843531923289, 'source_dataset': 'data'}


{'repo_name': 'nlmayday/niuniu', 'stars': '142', 'repo_language': 'JavaScript', 'file_name': 'plugin_string.xml', 'mime_type': 'text/xml', 'hash': 7257669255574754708, 'source_dataset': 'data'}