Example #1
0
static void command_read_cb (CFFileDescriptorRef fdref,
                             CFOptionFlags callBackTypes,
                             void *info)
{
    SeafWTMonitorPriv *priv = (SeafWTMonitorPriv *)info;
    WatchCommand cmd;
    int n;

    n = pipereadn (priv->cmd_pipe[0], &cmd, sizeof(cmd));
    if (n != sizeof(cmd)) {
        seaf_warning ("[wt mon] failed to read command.\n");
        CFFileDescriptorEnableCallBacks (fdref, kCFFileDescriptorReadCallBack);
        return;
    }

    seaf_debug ("[wt mon] %ld receive command type=%d, repo=%s\n",
                (long)CFRunLoopGetCurrent(), cmd.type, cmd.repo_id);
    handle_watch_command (priv, &cmd);
    CFFileDescriptorEnableCallBacks (fdref, kCFFileDescriptorReadCallBack);
}
Example #2
0
static void *
wt_monitor_job (void *vmonitor)
{
    SeafWTMonitor *monitor = vmonitor;
    SeafWTMonitorPriv *priv = monitor->priv;
    /* 2 * sizeof(inotify_event) + 256, should be large enough for one event.*/
    WTStatus *status;

    WatchCommand cmd;
    int n;
    int rc;
    fd_set fds;
    int inotify_fd;
    char event_buf[(sizeof(struct inotify_event) << 1) + 256];
    gpointer key, value;
    GHashTableIter iter;

    FD_SET (priv->cmd_pipe[0], &priv->read_fds);
    priv->maxfd = priv->cmd_pipe[0];

    while (1) {
        fds = priv->read_fds;

        rc = select (priv->maxfd + 1, &fds, NULL, NULL, NULL);
        if (rc < 0 && errno == EINTR) {
            continue;
        } else if (rc < 0) {
            seaf_warning ("[wt mon] select error: %s.\n", strerror(errno));
            break;
        }

        if (FD_ISSET (priv->cmd_pipe[0], &fds)) {
            n = pipereadn (priv->cmd_pipe[0], &cmd, sizeof(cmd));
            if (n != sizeof(cmd)) {
                seaf_warning ("[wt mon] failed to read command.\n");
                continue;
            }
            handle_watch_command (priv, &cmd);
        }

        g_hash_table_iter_init (&iter, priv->status_hash);
        while (g_hash_table_iter_next (&iter, &key, &value)) {
            inotify_fd = (int)(long)key;
            if (FD_ISSET (inotify_fd, &fds)) {
                /* We don't care about the details of the event now.
                 * So we just read out the data but don't parse it.
                 * We may read partial event structure.
                 */
                n = read (inotify_fd, event_buf, sizeof(event_buf));
                if (n <= 0) {
                    seaf_warning ("[wt mon] failed to read inotify event.\n");
                    continue;
                }
                status = value;
                if (status) {
                    g_atomic_int_set (&status->last_changed, (gint)time(NULL));
                }
            }
        }
    }

    return NULL;
}
Example #3
0
static void *
wt_monitor_job_win32 (void *vmonitor)
{
    SeafWTMonitor *monitor = vmonitor;
    SeafWTMonitorPriv *priv = monitor->priv;
    /* 2 * sizeof(inotify_event) + 256, should be large enough for one event.*/
    RepoWatchInfo *info;


    DWORD bytesRead = 0;
    ULONG_PTR key = 0;
    OVERLAPPED *ol = NULL;

    /* Use I/O Completion Port to watch asynchronous events on:

     * 1) dir watch handles(events created by ReadDirectoryChangesW)
     * 2) the cmd pipe (which is a socket indeed)
     
     */

    if (!add_all_to_iocp(monitor)) {
        seaf_warning("Failed to add all to iocp\n");
        return NULL;
    }
    
    while (1) {

        BOOL ret = GetQueuedCompletionStatus
            (priv->iocp_handle,           /* iocp handle */
             &bytesRead,                  /* length of info */
             &key,                        /* completion key */
             &ol,                         /* OVERLAPPED */
             INFINITE);                   /* timeout */

        static int retry;

        if (!ret) {
            seaf_warning ("GetQueuedCompletionStatus failed, "
                          "error code %lu", GetLastError());

            if (retry++ < 3)
                continue;
            else
                break;
        } else {
            /* clear the retry counter on success */
            retry = 0;
        }

        if (key == (ULONG_PTR)monitor->cmd_pipe[0]) {     
            /* Triggered by a cmd pipe event */

            if (bytesRead != sizeof(WatchCommand)) {
                seaf_warning ("broken cmd from pipe: get"
                              " %d(expected: %d) bytes\n",
                              (int)bytesRead, sizeof(WatchCommand));
                continue;
            }

            seaf_debug ("recevied a pipe cmd, type %d for repo %s\n",
                        priv->cmd.type, priv->cmd.repo_id);

            handle_watch_command (monitor, &priv->cmd);

            reset_overlapped(ol);
            start_watch_cmd_pipe (monitor, ol);

        } else {
            /* Trigger by one of the dir watch handles */

            HANDLE hTriggered = (HANDLE)key;
            info = (RepoWatchInfo *)g_hash_table_lookup
                (priv->info_hash, (gconstpointer)hTriggered); 

            if (info) {
                DirWatchAux *aux = g_hash_table_lookup (priv->buf_hash,
                                                        (gconstpointer)hTriggered);

                process_events (info->status->repo_id, info, aux->buf, bytesRead);

                reset_overlapped(ol);
                if (!start_watch_dir_change(priv, hTriggered)) {

                    seaf_warning ("start_watch_dir_change failed"
                                  "for repo %s, error code %lu\n",
                                  info->status->repo_id, GetLastError());
                }
            } else {
                /* A previously unwatched dir_handle's DirWatchAux buf was
                   scheduled to be freed. */
                DirWatchAux *aux = g_hash_table_lookup (priv->buf_hash, (gconstpointer)hTriggered);
                if (aux && aux->unused)
                    g_free (aux);
                g_hash_table_remove (priv->buf_hash, (gconstpointer)hTriggered);
            }
        }
    }
    return NULL;
}