Exemple #1
0
 /** 初始化epoll机制 */
 error_code cepoll_init(s64 ms, s32 * pnError) {
     errno = 0;
     s_epfd = epoll_create(MAX_FDS);
     if (0 == s_epfd) {
         RETURN_RES(ERROR_CREATE_EPOLL);
     }
     RETURN_RES(ERROR_NO_ERROR);
 }
Exemple #2
0
    /** 异步连接 */
    error_code async_connect(const char * pStrIP, s32 nPort, OUT s32 * pnError, void * pData) {
        struct epoll_event e;
        struct cepoll_event * pEvent = NULL;
        s32 s = socket(AF_INET, SOCK_STREAM, 0);
        errno = 0;
        if (-1 == fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK)) {
            RETURN_RES(ERROR_FCNTL);
        }

        pEvent = malloc_event();
        if (NULL == pEvent) {
            //assert(false);
            ECHO_ERROR("%s", "get cepoll_event error");
            RETURN_RES(ERROR_MALLOC_EVENT);
        }
        pEvent->s = s;
        pEvent->p = pData;
        pEvent->event = EVENT_ASYNC_CONNECT;


        e.events = EPOLLOUT | EPOLLET;
        e.data.ptr = pEvent;
        epoll_ctl(s_epfd, EPOLL_CTL_ADD, s, &e);

        if((pEvent->remote.sin_addr.s_addr = inet_addr(pStrIP)) == INADDR_NONE) {
            free_event(pEvent);
            RETURN_RES(ERROR_IP_FORMAT);
        }

        *pnError = connect(s, (struct sockaddr*)&pEvent->remote, sizeof(pEvent->remote));
        /*
        getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
        if( !error )
        {
        //OK
        }
        */
        *pnError = 100;
        return ERROR_CODE_MAX;
    }
Exemple #3
0
    error_code async_listen(const char * pStrIP, s32 nPort, OUT s32 * pnError, void * pData, s32 backlog) {
        ASSERT(pStrIP != NULL && pnError != NULL);
        errno = 0;
        struct epoll_event e;
        struct cepoll_event * pEvent = NULL;
        s32 s = socket(AF_INET, SOCK_STREAM, 0);
        if (-1 == (s = socket(AF_INET, SOCK_STREAM, 0))) {
            ECHO_ERROR("socket error %d", errno);
            return false;
        }
        //把socket设置为非阻塞方式
        if (!Setnonblocking(s)) {
            ECHO_ERROR("Setnonblocking error %d", errno);
            return false;
        }

        pEvent = malloc_event();
        if (NULL == pEvent) {
            //assert(false);
            ECHO_ERROR("%s", "get cepoll_event error");
            RETURN_RES(ERROR_MALLOC_EVENT);
        }

        struct sockaddr_in addr;
        memset(&addr, 0, sizeof (addr));
        addr.sin_family = AF_INET;
        inet_aton(pStrIp, &(addr.sin_addr));
        addr.sin_port = htons(nPort);

        if (-1 == bind(s, (sockaddr *) & addr, sizeof (addr)) ||
                -1 == (listen(s, LISTEN_QUENE))) {
            Assert(false);
            return false;
        }

        struct epoll_event ev;
        ev.data.ptr = pListen;
        ev.events = EPOLLIN; // | EPOLLET;
        epoll_ctl(m_epfd, EPOLL_CTL_ADD, listenfd, &ev);

        return true;
    }
Exemple #4
0
/* {{{ php_dba_open
 */
static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
	zval *args = NULL;
	int ac = ZEND_NUM_ARGS();
	dba_mode_t modenr;
	dba_info *info, *other;
	dba_handler *hptr;
	char *key = NULL, *error = NULL;
	int keylen = 0;
	int i;
	int lock_mode, lock_flag, lock_dbf = 0;
	char *file_mode;
	char mode[4], *pmode, *lock_file_mode = NULL;
	int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
	zend_string *opened_path = NULL;
	char *lock_name;

	if (ac < 2) {
		WRONG_PARAM_COUNT;
	}

	/* we pass additional args to the respective handler */
	args = safe_emalloc(ac, sizeof(zval), 0);
	if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
		efree(args);
		WRONG_PARAM_COUNT;
	}

	/* we only take string arguments */
	for (i = 0; i < ac; i++) {
		if (Z_TYPE(args[i]) != IS_STRING) {
			convert_to_string_ex(&args[i]);
		} else if (Z_REFCOUNTED(args[i])) {
			Z_ADDREF(args[i]);
		}
		keylen += Z_STRLEN(args[i]);
	}

	if (persistent) {
		zend_resource *le;

		/* calculate hash */
		key = safe_emalloc(keylen, 1, 1);
		key[keylen] = '\0';
		keylen = 0;

		for(i = 0; i < ac; i++) {
			memcpy(key+keylen, Z_STRVAL(args[i]), Z_STRLEN(args[i]));
			keylen += Z_STRLEN(args[i]);
		}

		/* try to find if we already have this link in our persistent list */
		if ((le = zend_hash_str_find_ptr(&EG(persistent_list), key, keylen)) != NULL) {
			FREENOW;

			if (le->type != le_pdb) {
				RETURN_FALSE;
			}

			info = (dba_info *)le->ptr;

			GC_REFCOUNT(le)++;
			RETURN_RES(le);
			return;
		}
	}

	if (ac==2) {
		hptr = DBA_G(default_hptr);
		if (!hptr) {
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No default handler selected");
			FREENOW;
			RETURN_FALSE;
		}
	} else {
		for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL(args[2])); hptr++);
	}

	if (!hptr->name) {
		php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL(args[2]));
		FREENOW;
		RETURN_FALSE;
	}

	/* Check mode: [rwnc][fl]?t?
	 * r: Read
	 * w: Write
	 * n: Create/Truncate
	 * c: Create
	 *
	 * d: force lock on database file
	 * l: force lock on lck file
	 * -: ignore locking
	 *
	 * t: test open database, warning if locked
	 */
	strlcpy(mode, Z_STRVAL(args[1]), sizeof(mode));
	pmode = &mode[0];
	if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
		switch (pmode[1]) {
		case 'd':
			lock_dbf = 1;
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				lock_flag = (hptr->flags & DBA_LOCK_ALL);
				break;
			}
			/* no break */
		case 'l':
			lock_flag = DBA_LOCK_ALL;
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name);
			}
			break;
		default:
		case '-':
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name);
				FREENOW;
				RETURN_FALSE;
			}
			lock_flag = 0;
			break;
		}
	} else {
		lock_flag = (hptr->flags&DBA_LOCK_ALL);
		lock_dbf = 1;
	}
	switch (*pmode++) {
		case 'r':
			modenr = DBA_READER;
			lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
			file_mode = "r";
			break;
		case 'w':
			modenr = DBA_WRITER;
			lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
			file_mode = "r+b";
			break;
		case 'c':
			modenr = DBA_CREAT;
			lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
			if (lock_mode) {
				if (lock_dbf) {
					/* the create/append check will be done on the lock
					 * when the lib opens the file it is already created
					 */
					file_mode = "r+b";       /* read & write, seek 0 */
					lock_file_mode = "a+b";  /* append */
				} else {
					file_mode = "a+b";       /* append */
					lock_file_mode = "w+b";  /* create/truncate */
				}
			} else {
				file_mode = "a+b";
			}
			/* In case of the 'a+b' append mode, the handler is responsible
			 * to handle any rewind problems (see flatfile handler).
			 */
			break;
		case 'n':
			modenr = DBA_TRUNC;
			lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
			file_mode = "w+b";
			break;
		default:
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode");
			FREENOW;
			RETURN_FALSE;
	}
	if (!lock_file_mode) {
		lock_file_mode = file_mode;
	}
	if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
		pmode++; /* done already - skip here */
	}
	if (*pmode=='t') {
		pmode++;
		if (!lock_flag) {
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)");
			FREENOW;
			RETURN_FALSE;
		}
		if (!lock_mode) {
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name);
				FREENOW;
				RETURN_FALSE;
			} else {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name);
				FREENOW;
				RETURN_FALSE;
			}
		} else {
			lock_mode |= LOCK_NB; /* test =: non blocking */
		}
	}
	if (*pmode) {
		php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode");
		FREENOW;
		RETURN_FALSE;
	}

	info = pemalloc(sizeof(dba_info), persistent);
	memset(info, 0, sizeof(dba_info));
	info->path = pestrdup(Z_STRVAL(args[0]), persistent);
	info->mode = modenr;
	info->argc = ac - 3;
	info->argv = args + 3;
	info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
	info->lock.mode = lock_mode;

	/* if any open call is a locking call:
	 * check if we already habe a locking call open that should block this call
	 * the problem is some systems would allow read during write
	 */
	if (hptr->flags & DBA_LOCK_ALL) {
		if ((other = php_dba_find(info->path)) != NULL) {
			if (   ( (lock_mode&LOCK_EX)        && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
			    || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH))        )
			   ) {
				error = "Unable to establish lock (database file already open)"; /* force failure exit */
			}
		}
	}

	if (!error && lock_mode) {
		if (lock_dbf) {
			lock_name = Z_STRVAL(args[0]);
		} else {
			spprintf(&lock_name, 0, "%s.lck", info->path);
			if (!strcmp(file_mode, "r")) {
				/* when in read only mode try to use existing .lck file first */
				/* do not log errors for .lck file while in read ony mode on .lck file */
				lock_file_mode = "rb";
				info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
			}
			if (!info->lock.fp) {
				/* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
				lock_file_mode = "a+b";
			} else {
				if (opened_path) {
					info->lock.name = pestrndup(opened_path->val, opened_path->len, persistent);
					zend_string_release(opened_path);
				}
			}
		}
		if (!info->lock.fp) {
			info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
			if (info->lock.fp) {
				if (lock_dbf) {
					/* replace the path info with the real path of the opened file */
					pefree(info->path, persistent);
					info->path = pestrndup(opened_path->val, opened_path->len, persistent);
				}
				/* now store the name of the lock */
				info->lock.name = pestrndup(opened_path->val, opened_path->len, persistent);
				zend_string_release(opened_path);
			}
		}
		if (!lock_dbf) {
			efree(lock_name);
		}
		if (!info->lock.fp) {
			dba_close(info);
			/* stream operation already wrote an error message */
			FREENOW;
			RETURN_FALSE;
		}
		if (!php_stream_supports_lock(info->lock.fp)) {
			error = "Stream does not support locking";
		}
		if (php_stream_lock(info->lock.fp, lock_mode)) {
			error = "Unable to establish lock"; /* force failure exit */
		}
	}

	/* centralised open stream for builtin */
	if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
		if (info->lock.fp && lock_dbf) {
			info->fp = info->lock.fp; /* use the same stream for locking and database access */
		} else {
			info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
		}
		if (!info->fp) {
			dba_close(info);
			/* stream operation already wrote an error message */
			FREENOW;
			RETURN_FALSE;
		}
		if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
			/* Needed because some systems do not allow to write to the original
			 * file contents with O_APPEND being set.
			 */
			if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
				php_error_docref(NULL, E_WARNING, "Could not cast stream");
				dba_close(info);
				FREENOW;
				RETURN_FALSE;
#ifdef F_SETFL
			} else if (modenr == DBA_CREAT) {
				int flags = fcntl(info->fd, F_SETFL);
				fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
#endif
			}

		}
	}

	if (error || hptr->open(info, &error) != SUCCESS) {
		dba_close(info);
		php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
		FREENOW;
		RETURN_FALSE;
	}

	info->hnd = hptr;
	info->argc = 0;
	info->argv = NULL;

	if (persistent) {
		zend_resource new_le;

		new_le.type = le_pdb;
		new_le.ptr = info;
		if (zend_hash_str_update_mem(&EG(persistent_list), key, keylen, &new_le, sizeof(zend_resource)) == NULL) {
			dba_close(info);
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Could not register persistent resource");
			FREENOW;
			RETURN_FALSE;
		}
	}

	RETVAL_RES(zend_register_resource(info, (persistent ? le_pdb : le_db)));
	FREENOW;
}