Beispiel #1
0
//
// CloseHandle() has a slightly different interface from the NT call. It takes an
// additional input parameter to determine the object type. The object can be either
// a FILE_ELEMENT or a CQ_ELEMENT.
//
// CloseHandle() closes the file handle or the completion queue handle and frees all
// the allocated memory. It does an additional check to ensure that all the queued
// Asynch I/Os that have not yet completed are cancelled before actually closing the
// handle. This helps clean up the kernel queues of any pending requests.
//
// Although it takes longer, this is acceptable since the code is not in the performance 
// critical region.
// 
BOOL CloseHandle(HANDLE object, int object_type)
{
	struct File *filep;
	struct IOCQ *cqid;
	int retval, i;

#ifdef _DEBUG
	cout << "CloseHandle() freeing : handle = " << object << " objecttype = " << object_type << endl;
#endif

	switch (object_type) {
	case FILE_ELEMENT:
		filep = (struct File *)object;
		cqid = filep->iocq;
		// cancel any pending aio requests.
		retval = aio_cancel64(filep->fd, NULL);
		while (retval == AIO_NOTCANCELED) {
			retval = aio_cancel64(filep->fd, NULL);
		}

		if (cqid != NULL && cqid->element_list != NULL && cqid->aiocb_list != NULL) {
			for (i = 0; i < cqid->size; i++) {
				if (cqid->element_list[i].aiocbp.aio_fildes != filep->fd)
					continue;

				// We are not interested in the return values of aio_error() and aio_return().
				// only have to dequeue all the requests.
				if (!cqid->aiocb_list[i])
					continue;

				retval = aio_error64(cqid->aiocb_list[i]);
				retval = aio_return64(cqid->aiocb_list[i]);
			}
		}
#if defined(IOMTR_OS_LINUX) || defined(IOMTR_OS_OSX) || defined(IOMTR_OS_SOLARIS)
		close(filep->fd);
#elif defined(IOMTR_OS_NETWARE)
		if (IsType(filep->type, LogicalDiskType))
			NXClose(filep->fd);
		else if (IsType(filep->type, PhysicalDiskType))
			MM_ReleaseIOObject(filep->fd);
#else
#warning ===> WARNING: You have to do some coding here to get the port done!
#endif
		break;
	case CQ_ELEMENT:
		cqid = (struct IOCQ *)object;

		// cancel any pending aio requests.
		for (i = 0; i < cqid->size; i++) {
			if (!cqid->aiocb_list[i])
				continue;

#if defined(IOMTR_OS_LINUX) || defined(IOMTR_OS_OSX) || defined(IOMTR_OS_NETWARE)
			/*
			 * In Linux, you crash (!) if the aiocpb isn't in your queue. :-(
			 * This code seems to occasionally do this...so I just cancel all
			 * AIOs for the queue, thus avoiding the problem of cancelling a
			 * message not in the queue.
			 */
			retval = aio_cancel64(cqid->element_list[i].aiocbp.aio_fildes, NULL);
#elif defined(IOMTR_OS_SOLARIS)
			retval = aio_cancel64(cqid->element_list[i].aiocbp.aio_fildes, cqid->aiocb_list[i]);
#else
#warning ===> WARNING: You have to do some coding here to get the port done!
#endif
			if (retval == AIO_NOTCANCELED) {
				retval = aio_error64(cqid->aiocb_list[i]);
				retval = aio_return64(cqid->aiocb_list[i]);
			}
		}

#if defined(IOMTR_OS_LINUX) || defined(IOMTR_OS_OSX) || defined(IOMTR_OS_SOLARIS)
		free(cqid->aiocb_list);
#elif defined(IOMTR_OS_NETWARE)
		NXMemFree(cqid->aiocb_list);
#else
#warning ===> WARNING: You have to do some coding here to get the port done!
#endif
		// Something strange here. If I free the element_list, the next round
		// of aio_write() and aio_read() calls fail. If I dont free this, then they
		// succeed. But then, there is a memory leak equal to the max number of outstanding
		// I/Os * sizeof(CQ_Element).    Does that mean that the above aio_cancel() calls
		// are broken ??? It should be mentioned here that the element_list holds the 
		// actual aiocb structures.
		//
		// It suddenly seems to be working now.
		// Remember to turn this "free" off when you hit the problem again.
		// NEED TO LOOK INTO THIS.
#if defined(IOMTR_OS_LINUX) || defined(IOMTR_OS_OSX) || defined(IOMTR_OS_SOLARIS)
		free(cqid->element_list);
		free(cqid);
#elif defined(IOMTR_OS_NETWARE)
		NXMemFree(cqid->element_list);
		NXMemFree(cqid);
#else
#warning ===> WARNING: You have to do some coding here to get the port done!
#endif
		break;
	default:
		break;
	}
	return (TRUE);
}
int TargetDisk::NWCloseDevice(HNDL handle)
{
	return MM_ReleaseIOObject(handle);
}