start epoll integration by upoll
authorJosé Bollo <jose.bollo@iot.bzh>
Tue, 5 Apr 2016 11:14:58 +0000 (13:14 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Tue, 5 Apr 2016 11:14:58 +0000 (13:14 +0200)
Change-Id: If137a21e6f411775446393525ad7512421d7780e
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
include/afb-plugin.h
include/afb-poll-itf.h [new file with mode: 0644]
src/CMakeLists.txt
src/afb-apis.c
src/main.c
src/utils-upoll.c [new file with mode: 0644]
src/utils-upoll.h [new file with mode: 0644]

index 88938e3..ba86e18 100644 (file)
@@ -61,19 +61,13 @@ enum AFB_Mode {
        AFB_MODE_GLOBAL
 };
 
-/*
-typedef enum AFB_pluginE AFB_pluginE;
-typedef enum AFB_sessionE AFB_sessionE;
-typedef void (*AFB_apiCB)(struct afb_req);
-typedef void (*AFB_freeCtxCB)(void*);
-typedef struct AFB_restapi AFB_restapi;
-typedef struct AFB_plugin AFB_plugin;
-*/
+struct afb_poll;
 
 struct AFB_interface
 {
        int verbosity;
        enum AFB_Mode mode;
+       struct afb_poll (*poll_open)(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure);
 };
 
 extern const struct AFB_plugin *pluginRegister (const struct AFB_interface *interface);
diff --git a/include/afb-poll-itf.h b/include/afb-poll-itf.h
new file mode 100644 (file)
index 0000000..4ce1fa4
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 IoT.bzh
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+struct afb_poll_itf
+{
+       int (*update)(void *data, uint32_t events);
+       void (*close)(void *data);
+};
+
+struct afb_poll
+{
+       const struct afb_poll_itf *itf;
+       void *data;
+};
+
index 7e02578..d8bddcf 100644 (file)
@@ -8,7 +8,9 @@ ADD_LIBRARY(src OBJECT
        afb-hreq.c
        afb-websock.c
        websock.c
-       verbose.c)
+       verbose.c
+       utils-upoll.c
+)
 
 INCLUDE_DIRECTORIES(${include_dirs})
 
index 7634dca..8dfac51 100644 (file)
 
 #include "afb-plugin.h"
 #include "afb-req-itf.h"
+#include "afb-poll-itf.h"
+
 #include "session.h"
 #include "afb-apis.h"
 #include "verbose.h"
+#include "utils-upoll.h"
 
 struct api_desc {
        struct AFB_plugin *plugin;      /* descriptor */
@@ -59,6 +62,12 @@ static int apis_count = 0;
 
 static const char plugin_register_function[] = "pluginRegister";
 
+static const struct afb_poll_itf upoll_itf = {
+       .update = (void*)upoll_update,
+       .close = (void*)upoll_close
+};
+
+
 int afb_apis_count()
 {
        return apis_count;
@@ -76,6 +85,15 @@ void afb_apis_free_context(int apiidx, void *context)
                free(context);
 }
 
+static struct afb_poll itf_poll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure)
+{
+       struct afb_poll result;
+       result.data = upoll_open(fd, events, process, closure);
+       result.itf = result.data ? &upoll_itf : NULL;
+       return result;
+}
+
+
 int afb_apis_add_plugin(const char *path)
 {
        struct api_desc *apis;
@@ -117,6 +135,7 @@ int afb_apis_add_plugin(const char *path)
        }
        interface->verbosity = 0;
        interface->mode = AFB_MODE_LOCAL;
+       interface->poll_open = itf_poll_open;
 
        /* init the plugin */
        plugin = pluginRegisterFct(interface);
index 37183e7..15f84b1 100644 (file)
@@ -26,6 +26,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <stdint.h>
 
 #include "afb-plugin.h"
 
diff --git a/src/utils-upoll.c b/src/utils-upoll.c
new file mode 100644 (file)
index 0000000..af4a616
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2016 IoT.bzh
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/epoll.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "utils-upoll.h"
+
+
+struct upoll
+{
+       int fd;
+       void (*process)(void *closure, int fd, uint32_t events);
+       void *closure;
+       struct upoll *next;
+};
+
+static int pollfd = 0;
+static struct upoll *head = NULL;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int upoll_is_valid(struct upoll *upoll)
+{
+       struct upoll *it = head;
+       while (it != NULL) {
+               if (it == upoll)
+                       return 1;
+               it = it->next;
+       }
+       return 0;
+}
+
+struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure)
+{
+       struct epoll_event e;
+       struct upoll *result;
+       int rc;
+
+       /* opens the epoll stream */
+       if (pollfd == 0) {
+               pollfd = epoll_create1(EPOLL_CLOEXEC);
+               if (pollfd == 0) {
+                       pollfd = dup(0);
+                       close(0);
+               }
+               if (pollfd < 0) {
+                       pollfd = 0;
+                       return NULL;
+               }
+       }
+
+       /* allocates */
+       result = malloc(sizeof *result);
+       if (result == NULL)
+               return NULL;
+
+       /* init */
+       result->fd = fd;
+       result->process = process;
+       result->closure = closure;
+       pthread_mutex_lock(&mutex);
+       result->next = head;
+       head = result;
+       pthread_mutex_unlock(&mutex);
+
+       /* records */
+       e.events = events;
+       e.data.ptr = result;
+       rc = epoll_ctl(pollfd, EPOLL_CTL_ADD, fd, &e);
+       if (rc == 0)
+               return result;
+
+       /* revert on error */
+       rc = errno;
+       upoll_close(result);
+       errno = rc;
+       return NULL;
+}
+
+int upoll_update(struct upoll *upoll, uint32_t events)
+{
+       struct epoll_event e;
+
+       assert(pollfd != 0);
+       assert(upoll_is_valid(upoll));
+
+       e.events = events;
+       e.data.ptr = upoll;
+       return epoll_ctl(pollfd, EPOLL_CTL_MOD, upoll->fd, &e);
+}
+
+void upoll_close(struct upoll *upoll)
+{
+       struct upoll **it;
+
+       assert(pollfd != 0);
+       assert(upoll_is_valid(upoll));
+
+       epoll_ctl(pollfd, EPOLL_CTL_DEL, upoll->fd, NULL);
+       pthread_mutex_lock(&mutex);
+       it = &head;
+       while (*it != upoll)
+               it = &(*it)->next;
+       *it = upoll->next;
+       pthread_mutex_unlock(&mutex);
+       free(upoll);
+}
+
+void upoll_wait(int timeout)
+{
+       int rc;
+       struct epoll_event e;
+       struct upoll *upoll;
+
+       if (pollfd == 0)
+               return;
+
+       rc = epoll_wait(pollfd, &e, 1, timeout);
+       if (rc == 1) {
+               upoll = e.data.ptr;
+               upoll->process(upoll->closure, upoll->fd, e.events);
+       }
+}
+
diff --git a/src/utils-upoll.h b/src/utils-upoll.h
new file mode 100644 (file)
index 0000000..24aaf41
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 IoT.bzh
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+struct upoll;
+
+extern int upoll_is_valid(struct upoll *upoll);
+
+extern struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure);
+
+extern int upoll_update(struct upoll *upoll, uint32_t events);
+
+extern void upoll_close(struct upoll *upoll);
+
+extern void upoll_wait(int timeout);
+