static void check_event(FAMConnection * fc) { int ret; FAMEvent fe; ret = FAMPending(fc); if (ret < 0) { fprintf(stderr, "FAMPending() failed\n"); exit(1); } while (ret > 0) { ret = FAMNextEvent(fc, &fe); if (ret < 0) { fprintf(stderr, "FAMNextEvent() failed\n"); exit(1); } print_event(&fe); ret = FAMPending(fc); if (ret < 0) { fprintf(stderr, "FAMPending() failed\n"); exit(1); } } }
static void viewer_fam_input(viewer_t *viewer, int fd, GdkInputCondition condition) { FAMEvent fe; while ( FAMPending(&(viewer->fc)) > 0 ) { if ( FAMNextEvent(&(viewer->fc), &fe) < 0 ) { fprintf(stderr, NAME ": WARNING: Failed to retrieve FAM event: %s\n", FamErrlist[FAMErrno]); fprintf(stderr, NAME ": WARNING: Disabling file update detection.\n"); viewer_fam_close(viewer); return; } switch ( fe.code ) { case FAMDeleted: case FAMMoved: viewer_clear(viewer); break; case FAMChanged: case FAMCreated: viewer_follow(viewer, 0); break; default: break; } } }
static void* fhs_event_process(void *data) { struct fe_handler *feh = (struct fe_handler*)data; FAMEvent fe; FAMRequest fr; FAMConnection fc; char* root_path; root_path = g_hash_table_lookup(feh->ohh->config, "root_path"); FAMOpen(&fc); FAMMonitorDirectory(&fc, root_path, &fr, REQ_RES); while(!feh->closing) { /* The old code is: FAMNextEvent(&fc, &fe); The new code is if (1 == FAMPending(&fc)) { FAMNextEvent(&fc, &fe); }else continue; In the old code, if this thread is processing FAMNextEvent and then feh->closing is set by another thread, this thread is still hung up. so the synchronized call is changed as asychronized call (polling call) though I don't like this mode. */ if (1 == FAMPending(&fc)) { FAMNextEvent(&fc, &fe); }else continue; if ((fe.userdata == REQ_RES) && ((fe.code == FAMCreated) || (fe.code == FAMExists))) { if (!IS_DIR(fe.filename)) fhs_event_add_resource(feh, fe.filename, &fe); }else if ((fe.userdata == REQ_RDR) && (fe.code == FAMDeleted)) { if (!IS_DIR(fe.filename)) fhs_event_remove_resource(feh, &fe); else printf("faint! why delete root path\n"); }else if (fe.userdata == REQ_RDR) { if (((fe.code == FAMChanged) || (fe.code == FAMExists))&& ((!strcmp(fe.filename, "reading"))|| (!strcmp(fe.filename, "thres")))) { fhs_event_sensor_update(feh, &fe); } } } FAMClose(&fc); return 0; }
gboolean ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn, MonoString **filename, gint *code, gint *reqnum) { FAMEvent ev; if (FAMNextEvent (conn, &ev) == 1) { *filename = mono_string_new (mono_domain_get (), ev.filename); *code = ev.code; *reqnum = ev.fr.reqnum; return TRUE; } return FALSE; }
static void* fhs_event_process(void *data) { struct fe_handler *feh = (struct fe_handler*)data; FAMEvent fe; FAMRequest fr; FAMConnection fc; char* root_path; #ifndef UNIT_TEST root_path = g_hash_table_lookup(feh->ohh->config, "root_path"); #else root_path = "/home/guorj/HPI/openhpi/src/plugins/simulator/test/resources"; #endif FAMOpen(&fc); FAMMonitorDirectory(&fc, root_path, &fr, (void*)req_res); while(!feh->done) { FAMNextEvent(&fc, &fe); if ((fe.userdata == (void *)req_res) && ((fe.code == FAMCreated) || (fe.code == FAMExists))) { if (!IS_DIR(fe.filename)) fhs_event_add_resource(feh, fe.filename, &fe); }else if ((fe.userdata == (void*) req_res) && (fe.code == FAMDeleted)) { if (!IS_DIR(fe.filename)) fhs_event_remove_resource(feh, &fe); else printf("faint! why delete root path\n"); }else if (fe.userdata == (void *)req_rdr) { if (((fe.code == FAMChanged) || (fe.code == FAMExists))&& ((!strcmp(fe.filename, "reading"))|| (!strcmp(fe.filename, "thres")))) { fhs_event_sensor_update(feh, &fe); } } } FAMClose(&fc); #if 0 free all resource id and rdr id; #endif return 0; }
static int printEvent(int no) { int ret; FAMEvent fe; char *data; ret = FAMNextEvent(&(testState.fc), &fe); if (ret < 0) { fprintf(stderr, "event(s) line %d: FAMNextEvent failed\n", no); return (-1); } testState.nb_events++; if (fe.userdata == NULL) data = "NULL"; else data = fe.userdata; printf("%d: %s %s: %s\n", fe.fr.reqnum, fe.filename, codeName(fe.code), data); return (0); }
handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent) { size_t i; stat_cache *sc = srv->stat_cache; size_t events; UNUSED(_fce); /* */ if (revent & FDEVENT_IN) { events = FAMPending(&sc->fam); for (i = 0; i < events; i++) { FAMEvent fe; fam_dir_entry *fam_dir; splay_tree *node; int ndx, j; FAMNextEvent(&sc->fam, &fe); /* handle event */ switch(fe.code) { case FAMChanged: case FAMDeleted: case FAMMoved: /* if the filename is a directory remove the entry */ fam_dir = fe.userdata; fam_dir->version++; /* file/dir is still here */ if (fe.code == FAMChanged) break; /* we have 2 versions, follow and no-follow-symlink */ for (j = 0; j < 2; j++) { buffer_copy_string(sc->hash_key, fe.filename); buffer_append_int(sc->hash_key, j); ndx = hashme(sc->hash_key); sc->dirs = splaytree_splay(sc->dirs, ndx); node = sc->dirs; if (node && (node->key == ndx)) { int osize = splaytree_size(sc->dirs); fam_dir_entry_free(&sc->fam, node->data); sc->dirs = splaytree_delete(sc->dirs, ndx); force_assert(osize - 1 == splaytree_size(sc->dirs)); } } break; default: break; } } } if (revent & FDEVENT_HUP) { /* fam closed the connection */ fdevent_event_del(srv->ev, &(sc->fam_fcce_ndx), FAMCONNECTION_GETFD(&sc->fam)); fdevent_unregister(srv->ev, FAMCONNECTION_GETFD(&sc->fam)); FAMClose(&sc->fam); } return HANDLER_GO_ON; }
/* event handler of all FAM events */ static gboolean on_fam_event( GIOChannel * channel, GIOCondition cond, gpointer user_data ) { #ifdef USE_INOTIFY /* Linux inootify */ #define BUF_LEN (1024 * (sizeof (struct inotify_event) + 16)) char buf[ BUF_LEN ]; int i, len; #else /* FAM|gamin */ FAMEvent evt; #endif VFSFileMonitor* monitor = NULL; if ( cond & (G_IO_HUP | G_IO_ERR) ) { disconnect_from_fam(); if ( g_hash_table_size ( monitor_hash ) > 0 ) { /* Disconnected from FAM server, but there are still monitors. This may be caused by crash of FAM server. So we have to reconnect to FAM server. */ connect_to_fam(); g_hash_table_foreach( monitor_hash, ( GHFunc ) reconnect_fam, NULL ); } return TRUE; /* don't need to remove the event source since it has been removed by disconnect_from_fam(). */ } #ifdef USE_INOTIFY /* Linux inotify */ while ( ( len = read ( inotify_fd, buf, BUF_LEN ) ) < 0 && errno == EINTR ); if ( len < 0 ) { g_warning ( "Error reading inotify event: %s", g_strerror ( errno ) ); /* goto error_cancel; */ return FALSE; } if ( len == 0 ) { /* * FIXME: handle this better? */ g_warning ( "Error reading inotify event: supplied buffer was too small" ); /* goto error_cancel; */ return FALSE; } i = 0; while ( i < len ) { struct inotify_event * ievent = ( struct inotify_event * ) & buf [ i ]; /* FIXME: 2 different paths can have the same wd because of link */ monitor = ( VFSFileMonitor* ) g_hash_table_find( monitor_hash, find_monitor, GINT_TO_POINTER( ievent->wd ) ); if( G_LIKELY(monitor) ) { const char* file_name; file_name = ievent->len > 0 ? ievent->name : monitor->path; /* //MOD for debug output only char* desc; if ( ievent->mask & ( IN_CREATE | IN_MOVED_TO ) ) desc = "CREATE"; else if ( ievent->mask & ( IN_DELETE | IN_MOVED_FROM | IN_DELETE_SELF | IN_UNMOUNT ) ) desc = "DELETE"; else if ( ievent->mask & ( IN_MODIFY | IN_ATTRIB ) ) desc = "CHANGE"; if ( !strcmp( monitor->path, "/tmp" ) && g_str_has_prefix( file_name, "vte" ) ) { } // due to current vte scroll problems creating and deleting massive numbers of // /tmp/vte8CBO7V types of files, ignore these (creates feedback loop when // spacefm is run in terminal because each printf triggers a scroll, // which triggers another printf below, which triggers another file change) // https://bugs.launchpad.net/ubuntu/+source/vte/+bug/778872 else printf("inotify-event %s: %s///%s\n", desc, monitor->path, file_name); //g_debug("inotify (%d) :%s", ievent->mask, file_name); */ dispatch_event( monitor, translate_inotify_event( ievent->mask ), file_name ); } i += sizeof ( struct inotify_event ) + ievent->len; } #else /* FAM|gamin */ while ( FAMPending( &fam ) ) { if ( FAMNextEvent( &fam, &evt ) > 0 ) { monitor = ( VFSFileMonitor* ) evt.userdata; switch ( evt.code ) { case FAMCreated: case FAMDeleted: case FAMChanged: /* FIXME: There exists a possibility that a file can accidentally become a directory, and a directory can become a file when using chmod. Should we delete original request, and create a new one when this happens? */ /* g_debug("FAM event(%d): %s", evt.code, evt.filename); */ /* Call the callback functions */ dispatch_event( monitor, evt.code, evt.filename ); break; /* Other events are not supported */ default: break; } } } #endif return TRUE; }
static gboolean g_fam_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_data) { gint64 now = g_source_get_time (fam_source); g_mutex_lock (&fam_lock); while (FAMPending (&fam_connection)) { const gchar *child; FAMEvent ev; if (FAMNextEvent (&fam_connection, &ev) != 1) { /* The daemon died. We're in a really bad situation now * because we potentially have a bunch of request structures * outstanding which no longer make any sense to anyone. * * The best thing that we can do is do nothing. Notification * won't work anymore for this process. */ g_mutex_unlock (&fam_lock); g_warning ("Lost connection to FAM (file monitoring) service. Expect no further file monitor events."); return FALSE; } /* We expect ev.filename to be a relative path for children in a * monitored directory, and an absolute path for a monitored file * or the directory itself. */ if (ev.filename[0] != '/') child = ev.filename; else child = NULL; switch (ev.code) { case FAMAcknowledge: g_source_unref (ev.userdata); break; case FAMChanged: g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CHANGED, child, NULL, NULL, now); break; case FAMDeleted: g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_DELETED, child, NULL, NULL, now); break; case FAMCreated: g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CREATED, child, NULL, NULL, now); break; default: /* unknown type */ break; } } g_mutex_unlock (&fam_lock); return TRUE; }
/** * Process all pending events. * Helper thread for the worker thread. Just there * to process FAM events. Puts all events into the * queue for the main worker. */ static void * processEvents(void * arg) { DIC * cls = arg; FAMEvent fe; fd_set r; fd_set w; fd_set e; int fd = cls->fc.fd; int i; cls->log(cls->logContext, DOODLE_LOG_VERY_VERBOSE, _("Event processing thread created.\n")); while ( (0 == testShutdown()) && (cls->continueRunning) ) { char * name; FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); FD_SET(fd, &r); i = select(fd+1, &r, &w, &e, NULL); if (i == -1) { if (errno == EINTR) continue; cls->log(cls->logContext, DOODLE_LOG_CRITICAL, _("Call to '%s' failed: %s\n"), "select", strerror(errno)); } if (!FD_ISSET(fd, &r)) continue; if (! FAMPending(&cls->fc)) { /* this should only happen if there was a problem with select, and in this case we better add some artificial delay (busy waiting) */ sleep(1); continue; } MUTEX_LOCK(&cls->lock); if (-1 == FAMNextEvent(&cls->fc, &fe)) { cls->log(cls->logContext, DOODLE_LOG_CRITICAL, _("Call to '%s' failed: %s\n"), "FAMNextEvent", FamErrlist[FAMErrno]); /* avoid fast, persistent errors */ sleep(1); continue; } name = malloc(strlen(fe.filename) + strlen((char*) fe.userdata) + 2); if (fe.filename[0] == '/') { strcpy(name, fe.filename); } else { strcpy(name, (char*) fe.userdata); if ( (strlen((char*)fe.userdata) > 0) && (((char*)fe.userdata)[strlen(fe.userdata)-1] != DIR_SEPARATOR) ) strcat(name, DIR_SEPARATOR_STR); strcat(name, fe.filename); } /* never process the doodle database itself... */ if (0 == strncmp(name, cls->ename, strlen(cls->ename))) { free(name); MUTEX_UNLOCK(&cls->lock); continue; } cls->log(cls->logContext, DOODLE_LOG_INSANELY_VERBOSE, "FAM EVENT (%d,%s,%s) on file '%s'.\n", fe.code, fe.userdata, fe.filename, name); switch (fe.code) { case FAMCreated: case FAMChanged: case FAMDeleted: case FAMMoved: case FAMAcknowledge: case FAMExists: case FAMEndExist: GROW(cls->events, cls->eventCount, cls->eventCount+1); cls->events[cls->eventCount-1] = strdup(name); SEMAPHORE_UP(cls->signal); break; default: break; } /* end switch */ free(name); MUTEX_UNLOCK(&cls->lock); } /* if event */ cls->continueRunning = 0; SEMAPHORE_UP(cls->signal); return NULL; }
- failwith("No file descriptors in pseudo-FAM"); + caml_failwith("No file descriptors in pseudo-FAM"); return Val_unit; #endif /* FAM_INOTIFY */ #else /* FAM_PSEUDO */ @@ -209,7 +209,7 @@ value om_notify_monitor_directory(value #ifdef WIN32 CheckCode("om_notify_monitor_directory", FAMMonitorDirectoryTree(fc, name, &request, 0)); #else /* WIN32 */ - failwith("om_notify_monitor_directory: recursive monitoring is not allowed"); + caml_failwith("om_notify_monitor_directory: recursive monitoring is not allowed"); #endif /* !WIN32 */ } else @@ -294,13 +294,13 @@ value om_notify_next_event(value v_fc) CheckCode("om_notify_next_event", FAMNextEvent(fc, &event)); code = event.code; if(code < 1 || code > 10) - failwith("om_notify_next_event: code out of bounds"); + caml_failwith("om_notify_next_event: code out of bounds"); /* Allocate the string name */ - v_name = copy_string(event.filename); + v_name = caml_copy_string(event.filename); /* Allocate the tuple */ - v_tuple = alloc_tuple(3); + v_tuple = caml_alloc_tuple(3); Field(v_tuple, 0) = Val_int(event.fr.reqnum); Field(v_tuple, 1) = v_name; Field(v_tuple, 2) = Val_int(code - 1);
int main(int argc, char **argv) { vector<string> cfg; size_t cfg_num = 0; if(argc==2) { cfg.push_back(argv[1]); } else if(argc==3) { cfg.push_back(argv[1]); cfg.push_back(argv[2]); } else { cfg.push_back(CONFIG_FILE); } time_t mtime; struct stat s; if (stat(cfg[cfg_num].c_str(), &s) == 0) { mtime = s.st_mtime; } else { mtime = 0; } cout << "BBC MDI Generator Rev " << svn_version() << ", using libsdixml Rev " << libsdixml::svn_version() << endl << "Implementing SDI Schema version " << libsdixml::SDI_Schema_version() << endl << "Reading config from " << cfg[cfg_num] << endl; cout.flush(); Mdigen mdigen; /* DcpIn dcpin; dcpin.ReConfigure("dcp.udp://:9998"); tagpacketlist t; dcpin.getFrame(t); for(tagpacketlist::iterator i=t.begin(); i!=t.end(); i++) cout << i->first << " " << i->second.size() << endl; */ #ifdef WIN32 int iResult; WSADATA wsaData; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); exit(1); } #else struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = signal_handler; if (sigaction(SIGHUP, &sa, NULL) == -1) { cerr << "error assigning signal handler" << endl; exit(1); } FAMConnection fc; if(FAMOpen(&fc)==0) { FAMRequest fr; if(cfg[0][0]!='/') { string path = getenv("PWD"); cerr << path << endl; cfg[0] = path + "/" + cfg[0]; } if(FAMMonitorFile(&fc, cfg[0].c_str(), &fr, NULL)) cerr << "can't monitor " << cfg[0] << endl; else cout << "FAM Monitoring " << cfg[0] << endl; } else { cerr << "can't connect to file alteration monitor " << endl; } #endif bool ok = true; int max_frames = -1; int reconf_interval = 32; int reconf = reconf_interval; ReConfigure(mdigen, cfg[cfg_num], ok, max_frames); while(ok) { try { mdigen.eachframe(); //cout << "Frame: " << mdigen.transmitted_frames << endl; #ifndef WIN32 while(FAMPending(&fc)) { FAMEvent fe; FAMNextEvent(&fc, &fe); switch(fe.code) { case FAMDeleted: break; case FAMChanged: cout << "file alteration monitor detected config change" << endl; reconfiguration_requested = true; break; case FAMCreated: case FAMExists: break; case FAMEndExist: cout << "FAM initialised " << fe.filename << endl; break; case FAMAcknowledge: cout << "FAM cancel acknowledged " << fe.filename << endl; break; case FAMStartExecuting: case FAMStopExecuting: case FAMMoved: cout << "unexpected fam event " << fe.code << " '" << fe.filename << "'" << endl; break; default: cout << "unknown fam event " << fe.code << " '" << fe.filename << "'" << endl; } } #endif } catch(char const* e) { cerr << e << endl; cerr.flush(); } if(reconfiguration_requested) { ReConfigure(mdigen, cfg[cfg_num], ok, max_frames); } if(cfg.size()>1) { reconf--; if(reconf==0) { cfg_num = 1 - cfg_num; ReConfigure(mdigen, cfg[cfg_num], ok, max_frames); reconf = reconf_interval; } } if(max_frames!=-1 && mdigen.transmitted_frames > max_frames) break; } }