wdm 0.0.2-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Maher Sallam
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ # Windows Directory Monitor (WDM)
2
+
3
+ Windows Directory Monitor (WDM) is a library which can be used to monitor directories for changes.
4
+ It's mostly implemented in C and uses the Win32 API for a better performance.
5
+
6
+ **Note:** This is still a work in progress, so it's not advisable to use
7
+ it yet in anything (unless you are testing it, which is very much appreciated :)).
8
+
9
+ TODO:
10
+
11
+ - Fix all the TODO's in the source.
12
+ - ~~Enable watching subdirectories.~~
13
+ - ~~Add options to the `watch` method.~~
14
+ - ~~Provide info about the change in the callback.~~
15
+ - ~~Convert \ to / in paths.~~
16
+ - ~~Don't allow directories to be watched while the monitor is running.~~
17
+ - ~~Check if the passed direcoty exists.~~
18
+ - ~~Convert passed directories to absolute paths.~~
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'wdm'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install wdm
33
+
34
+ ## Compiling the extension for developers
35
+
36
+ Download the source, then run the following:
37
+
38
+ $ rake compile
39
+
40
+ To get debug messages, you need to enable them in the `global.h` file:
41
+
42
+ #define WDM_DEBUG_ENABLED TRUE // This is disabled by default
43
+
44
+ ## Usage
45
+
46
+ TODO: Write usage instructions here
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
55
+
56
+ ## Author
57
+
58
+ [Maher Sallam](https://github.com/Maher4Ever)
@@ -0,0 +1,67 @@
1
+ #include "wdm.h"
2
+
3
+ #include "memory.h"
4
+ #include "entry.h"
5
+
6
+ // ---------------------------------------------------------
7
+ // Entry user data functions
8
+ // ---------------------------------------------------------
9
+
10
+ WDM_PEntryUserData
11
+ wdm_entry_user_data_new() {
12
+ WDM_PEntryUserData user_data;
13
+
14
+ user_data = WDM_ALLOC(WDM_EntryUserData);
15
+
16
+ user_data->dir = NULL;
17
+ user_data->watch_childeren = FALSE;
18
+
19
+ return user_data;
20
+ }
21
+
22
+ void
23
+ wdm_entry_user_data_free(WDM_PEntryUserData user_data) {
24
+ if ( user_data->dir != NULL ) free(user_data->dir);
25
+ free(user_data);
26
+ }
27
+
28
+ // ---------------------------------------------------------
29
+ // Entry functions
30
+ // ---------------------------------------------------------
31
+
32
+ WDM_PEntry
33
+ wdm_entry_new() {
34
+ WDM_PEntry entry;
35
+
36
+ entry = WDM_ALLOC(WDM_Entry);
37
+
38
+ entry->user_data = wdm_entry_user_data_new();
39
+ entry->dir_handle = INVALID_HANDLE_VALUE;
40
+ entry->next = NULL;
41
+
42
+ ZeroMemory(&entry->buffer, WDM_BUFFER_SIZE);
43
+ ZeroMemory(&entry->event_container, sizeof(OVERLAPPED));
44
+
45
+ return entry;
46
+ }
47
+
48
+ void
49
+ wdm_entry_free(WDM_PEntry entry) {
50
+ if ( entry->dir_handle != INVALID_HANDLE_VALUE ) {
51
+ CancelIo(entry->dir_handle); // Stop monitoring changes
52
+ CloseHandle(entry->dir_handle);
53
+ }
54
+ wdm_entry_user_data_free(entry->user_data);
55
+ free(entry);
56
+ }
57
+
58
+ void
59
+ wdm_entry_list_free(WDM_PEntry entry) {
60
+ WDM_PEntry tmp;
61
+
62
+ while(entry != NULL) {
63
+ tmp = entry;
64
+ entry = entry->next;
65
+ wdm_entry_free(tmp);
66
+ }
67
+ }
@@ -0,0 +1,47 @@
1
+ #include <Windows.h>
2
+ #include <ruby.h>
3
+
4
+ #ifndef WDM_ENTRY_H
5
+ #define WDM_ENTRY_H
6
+
7
+ #ifdef __cplusplus
8
+ extern "C" {
9
+ #endif // __cplusplus
10
+
11
+ // ---------------------------------------------------------
12
+ // Types
13
+ // ---------------------------------------------------------
14
+
15
+ typedef struct {
16
+ LPWSTR dir; // Name of directory to watch
17
+ VALUE callback; // Proc object to call when there are changes
18
+ BOOL watch_childeren; // Watch sub-directories
19
+ DWORD flags; // Flags for the type of changes to report
20
+ } WDM_EntryUserData, *WDM_PEntryUserData;
21
+
22
+ typedef struct WDM_Entry {
23
+ WDM_PEntryUserData user_data; // User-supplied data
24
+ HANDLE dir_handle; // IO handle of the directory
25
+ BYTE buffer[WDM_BUFFER_SIZE]; // Buffer for the results
26
+ OVERLAPPED event_container; // Async IO event container
27
+ struct WDM_Entry* next; // Well, this is a linked list, so this is self-explanatory :)
28
+ } WDM_Entry, *WDM_PEntry;
29
+
30
+ // ---------------------------------------------------------
31
+ // Prototypes
32
+ // ---------------------------------------------------------
33
+
34
+ WDM_PEntryUserData wdm_entry_user_data_new();
35
+ void wdm_entry_user_data_free(WDM_PEntryUserData);
36
+
37
+ WDM_PEntry wdm_entry_new();
38
+ void wdm_entry_free(WDM_PEntry);
39
+ void wdm_entry_list_free(WDM_PEntry);
40
+
41
+ // ---------------------------------------------------------
42
+
43
+ #ifdef __cplusplus
44
+ }
45
+ #endif // __cplusplus
46
+
47
+ #endif // WDM_ENTRY_H
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+
3
+ if have_library("kernel32") and
4
+ have_header("windows.h") and
5
+ have_header("ruby.h") and
6
+ have_const('HAVE_RUBY_ENCODING_H')
7
+ then
8
+ create_makefile("wdm")
9
+ end
@@ -0,0 +1,27 @@
1
+ #include "wdm.h"
2
+
3
+ #include "memory.h"
4
+
5
+ void *
6
+ wdm_memory_malloc (size_t size)
7
+ {
8
+ void *memory = malloc(size);
9
+
10
+ if ( memory == NULL ) {
11
+ rb_fatal("failed to allocate memory");
12
+ }
13
+
14
+ return memory;
15
+ }
16
+
17
+ void *
18
+ wdm_memory_realloc (void *ptr, size_t size)
19
+ {
20
+ void *memory = realloc(ptr, size);
21
+
22
+ if ( memory == NULL ) {
23
+ rb_fatal("failed to re-allocate memory");
24
+ }
25
+
26
+ return memory;
27
+ }
@@ -0,0 +1,32 @@
1
+ #ifndef WDM_MEMORY_H
2
+ #define WDM_MEMORY_H
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif // __cplusplus
7
+
8
+ // ---------------------------------------------------------
9
+ // Prototypes
10
+ // ---------------------------------------------------------
11
+
12
+ void *
13
+ wdm_memory_malloc (size_t);
14
+
15
+ void *
16
+ wdm_memory_realloc (void *, size_t);
17
+
18
+ // ---------------------------------------------------------
19
+ // Macros
20
+ // ---------------------------------------------------------
21
+
22
+ #define WDM_ALLOC_N(type,n) ((type*)wdm_memory_malloc((n) * sizeof(type)))
23
+ #define WDM_ALLOC(type) ((type*)wdm_memory_malloc(sizeof(type)))
24
+ #define WDM_REALLOC_N(var,type,n) ((var)=(type*)wdm_memory_realloc((void*)(var), (n) * sizeof(type)))
25
+
26
+ // ---------------------------------------------------------
27
+
28
+ #ifdef __cplusplus
29
+ }
30
+ #endif // __cplusplus
31
+
32
+ #endif // WDM_MEMORY_H
@@ -0,0 +1,70 @@
1
+ #include "wdm.h"
2
+
3
+ #include "memory.h"
4
+ #include "entry.h"
5
+ #include "queue.h"
6
+
7
+ #include "monitor.h"
8
+
9
+ WDM_PMonitor
10
+ wdm_monitor_new() {
11
+ WDM_PMonitor monitor;
12
+
13
+ monitor = WDM_ALLOC(WDM_Monitor);
14
+
15
+ monitor->running = FALSE;
16
+
17
+ monitor->head = NULL;
18
+ monitor->monitoring_thread = INVALID_HANDLE_VALUE;
19
+
20
+ monitor->changes = wdm_queue_new();
21
+
22
+ monitor->process_event = CreateEvent(NULL, TRUE, FALSE, NULL);
23
+ monitor->stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
24
+
25
+ if ( ! InitializeCriticalSectionAndSpinCount(&monitor->lock,
26
+ 0x00000400) ) // TODO: look into the best value for spinning.
27
+ {
28
+ rb_raise(eWDM_Error, "Can't create a lock for the monitor");
29
+ }
30
+
31
+ return monitor;
32
+ }
33
+
34
+ void
35
+ wdm_monitor_free(WDM_PMonitor monitor) {
36
+ if ( monitor->monitoring_thread != INVALID_HANDLE_VALUE ) CloseHandle(monitor->monitoring_thread);
37
+
38
+ wdm_entry_list_free(monitor->head);
39
+ wdm_queue_free(monitor->changes);
40
+ DeleteCriticalSection(&monitor->lock);
41
+ CloseHandle(monitor->process_event); // TODO: Look into why this crashes the app when exiting!
42
+ CloseHandle(monitor->stop_event);
43
+
44
+ free(monitor);
45
+ }
46
+
47
+ void
48
+ wdm_monitor_update_head(WDM_PMonitor monitor, WDM_PEntry new_head) {
49
+ EnterCriticalSection(&monitor->lock);
50
+ new_head->next = monitor->head;
51
+ monitor->head = new_head;
52
+ LeaveCriticalSection(&monitor->lock);
53
+ }
54
+
55
+ WDM_PMonitorCallbackParam
56
+ wdm_monitor_callback_param_new(WDM_PMonitor monitor, WDM_PEntry entry) {
57
+ WDM_PMonitorCallbackParam param;
58
+
59
+ param = WDM_ALLOC(WDM_MonitorCallbackParam);
60
+
61
+ param->monitor = monitor;
62
+ param->entry = entry;
63
+
64
+ return param;
65
+ }
66
+
67
+ void
68
+ wdm_monitor_callback_param_free(WDM_PMonitorCallbackParam param) {
69
+ free(param);
70
+ }
@@ -0,0 +1,50 @@
1
+ #include <Windows.h>
2
+
3
+ #include "entry.h"
4
+ #include "queue.h"
5
+
6
+ #ifndef WDM_MONITOR_H
7
+ #define WDM_MONITOR_H
8
+
9
+ #ifdef __cplusplus
10
+ extern "C" {
11
+ #endif // __cplusplus
12
+
13
+ // ---------------------------------------------------------
14
+ // Types
15
+ // ---------------------------------------------------------
16
+
17
+ typedef struct {
18
+ BOOL running;
19
+ WDM_PEntry head;
20
+ WDM_PQueue changes;
21
+ CRITICAL_SECTION lock;
22
+ HANDLE monitoring_thread;
23
+ HANDLE process_event;
24
+ HANDLE stop_event;
25
+ } WDM_Monitor, *WDM_PMonitor;
26
+
27
+ typedef struct {
28
+ WDM_PEntry entry;
29
+ WDM_PMonitor monitor;
30
+ } WDM_MonitorCallbackParam, *WDM_PMonitorCallbackParam;
31
+
32
+ // ---------------------------------------------------------
33
+ // Prototypes
34
+ // ---------------------------------------------------------
35
+
36
+ WDM_PMonitor wdm_monitor_new();
37
+ void wdm_monitor_free(WDM_PMonitor);
38
+
39
+ void wdm_monitor_update_head(WDM_PMonitor, WDM_PEntry);
40
+
41
+ WDM_PMonitorCallbackParam wdm_monitor_callback_param_new(WDM_PMonitor, WDM_PEntry);
42
+ void wdm_monitor_callback_param_free(WDM_PMonitorCallbackParam);
43
+
44
+ // ---------------------------------------------------------
45
+
46
+ #ifdef __cplusplus
47
+ }
48
+ #endif // __cplusplus
49
+
50
+ #endif // WDM_MONITOR_H
@@ -0,0 +1,108 @@
1
+ #include "wdm.h"
2
+
3
+ #include "memory.h"
4
+ #include "queue.h"
5
+
6
+ // ---------------------------------------------------------
7
+ // Queue item functions
8
+ // ---------------------------------------------------------
9
+
10
+ WDM_PQueueItem
11
+ wdm_queue_item_new() {
12
+ WDM_PQueueItem item;
13
+
14
+ item = WDM_ALLOC(WDM_QueueItem);
15
+ item->user_data = NULL;
16
+ item->previous = NULL;
17
+ item->next = NULL;
18
+
19
+ ZeroMemory(&item->buffer, WDM_BUFFER_SIZE);
20
+
21
+ return item;
22
+ }
23
+
24
+ void
25
+ wdm_queue_item_free(WDM_PQueueItem item) {
26
+ // We can't really do anything to the prev pointer nor the next pointer,
27
+ // because we might break any linking the user has established.
28
+ free(item);
29
+ }
30
+
31
+ // ---------------------------------------------------------
32
+ // Queue functions
33
+ // ---------------------------------------------------------
34
+
35
+ WDM_PQueue
36
+ wdm_queue_new() {
37
+ WDM_PQueue queue;
38
+
39
+ queue = WDM_ALLOC(WDM_Queue);
40
+ queue->front = NULL;
41
+ queue->rear = NULL;
42
+
43
+ if ( ! InitializeCriticalSectionAndSpinCount(&queue->lock,
44
+ 0x00000400) ) // TODO: look into the best value for spinning.
45
+ {
46
+ rb_raise(eWDM_Error, "Can't create a lock for the queue");
47
+ }
48
+
49
+ return queue;
50
+ }
51
+
52
+ void
53
+ wdm_queue_free(WDM_PQueue queue) {
54
+ wdm_queue_empty(queue);
55
+ free(queue);
56
+ }
57
+
58
+ void
59
+ wdm_queue_enqueue(WDM_PQueue queue, WDM_PQueueItem item) {
60
+ EnterCriticalSection(&queue->lock);
61
+
62
+ if ( queue->rear == NULL && queue->front == NULL ) {
63
+ queue->front = queue->rear = item;
64
+ }
65
+ else {
66
+ queue->rear->next = item;
67
+ item->previous = queue->rear;
68
+ queue->rear = item;
69
+ }
70
+
71
+ LeaveCriticalSection(&queue->lock);
72
+ }
73
+
74
+ WDM_PQueueItem
75
+ wdm_queue_dequeue(WDM_PQueue queue) {
76
+ WDM_PQueueItem item;
77
+
78
+ EnterCriticalSection(&queue->lock);
79
+
80
+ if ( queue->rear == NULL && queue->front == NULL ) {
81
+ item = NULL;
82
+ }
83
+ else {
84
+ item = queue->front;
85
+ queue->front = queue->front->next;
86
+
87
+ // Reset the rear when the queue is empty
88
+ if ( queue->front == NULL ) queue->rear = NULL;
89
+
90
+ // Don't allow the user to mess with the queue
91
+ item->previous = item->next = NULL;
92
+ }
93
+
94
+ LeaveCriticalSection(&queue->lock);
95
+
96
+ return item;
97
+ }
98
+
99
+ void wdm_queue_empty(WDM_PQueue queue) {
100
+ while( ! wdm_queue_is_empty(queue) ) {
101
+ wdm_queue_item_free(wdm_queue_dequeue(queue));
102
+ }
103
+ }
104
+
105
+ BOOL
106
+ wdm_queue_is_empty(WDM_PQueue queue) {
107
+ return queue->front == NULL && queue->rear == NULL;
108
+ }