eventmachine 0.4.0 → 0.4.2

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.
@@ -1,7 +1,20 @@
1
- $Id: RELEASE_NOTES 2283 2006-04-13 10:17:37Z francis $
1
+ $Id: RELEASE_NOTES 2326 2006-04-19 16:16:16Z francis $
2
2
 
3
3
  RUBY/EventMachine RELEASE NOTES
4
4
 
5
+ --------------------------------------------------
6
+ Version: 0.4.2, released 19Apr06
7
+ Changed the Ruby-glue so the extension will play nicer
8
+ in the sandbox with Ruby threads.
9
+ Added an EventMachine::run_without_threads API to
10
+ switch off the thread-awareness for better performance
11
+ in programs that do not spin any Ruby threads.
12
+
13
+ --------------------------------------------------
14
+ Version: 0.4.1, released 15Apr06
15
+ Reworked the shared-object interface to make it easier to
16
+ use EventMachine from languages other than Ruby.
17
+
5
18
  --------------------------------------------------
6
19
  Version: 0.3.2, released 12Apr06
7
20
  Added support for a user-supplied block in EventMachine#connect.
@@ -0,0 +1,146 @@
1
+ /*****************************************************************************
2
+
3
+ $Id: libmain.cpp 2291 2006-04-14 03:56:18Z francis $
4
+
5
+ File: libmain.cpp
6
+ Date: 06Apr06
7
+
8
+ Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
9
+ Gmail: garbagecat20
10
+
11
+ This program is free software; you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License as published by
13
+ the Free Software Foundation; either version 2 of the License, or
14
+ (at your option) any later version.
15
+
16
+ This program is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License
22
+ along with this program; if not, write to the Free Software
23
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
+
25
+ *****************************************************************************/
26
+
27
+ #include "project.h"
28
+
29
+
30
+ static EventMachine_t *EventMachine;
31
+
32
+
33
+ /***********************
34
+ evma_initialize_library
35
+ ***********************/
36
+
37
+ extern "C" void evma_initialize_library (void(*cb)(const char*, int, const char*, int))
38
+ {
39
+ // Probably a bad idea to mess with the signal mask of a process
40
+ // we're just being linked into.
41
+ //InstallSignalHandlers();
42
+ if (EventMachine)
43
+ throw std::runtime_error ("already initialized");
44
+ EventMachine = new EventMachine_t (cb);
45
+ }
46
+
47
+
48
+ /********************
49
+ evma_release_library
50
+ ********************/
51
+
52
+ extern "C" void evma_release_library()
53
+ {
54
+ if (!EventMachine)
55
+ throw std::runtime_error ("not initialized");
56
+ delete EventMachine;
57
+ EventMachine = NULL;
58
+ }
59
+
60
+
61
+ /****************
62
+ evma_run_machine
63
+ ****************/
64
+
65
+ extern "C" void evma_run_machine()
66
+ {
67
+ if (!EventMachine)
68
+ throw std::runtime_error ("not initialized");
69
+ EventMachine->Run();
70
+ }
71
+
72
+
73
+ /**************************
74
+ evma_install_oneshot_timer
75
+ **************************/
76
+
77
+ extern "C" const char *evma_install_oneshot_timer (int seconds)
78
+ {
79
+ if (!EventMachine)
80
+ throw std::runtime_error ("not initialized");
81
+ return EventMachine->InstallOneshotTimer (seconds);
82
+ }
83
+
84
+
85
+ /**********************
86
+ evma_connect_to_server
87
+ **********************/
88
+
89
+ extern "C" const char *evma_connect_to_server (const char *server, int port)
90
+ {
91
+ if (!EventMachine)
92
+ throw std::runtime_error ("not initialized");
93
+ return EventMachine->ConnectToServer (server, port);
94
+ }
95
+
96
+
97
+ /**********************
98
+ evma_create_tcp_server
99
+ **********************/
100
+
101
+ extern "C" const char *evma_create_tcp_server (const char *address, int port)
102
+ {
103
+ if (!EventMachine)
104
+ throw std::runtime_error ("not initialized");
105
+ return EventMachine->CreateTcpServer (address, port);
106
+ }
107
+
108
+
109
+ /****************************
110
+ evma_send_data_to_connection
111
+ ****************************/
112
+
113
+ extern "C" int evma_send_data_to_connection (const char *binding, const char *data, int data_length)
114
+ {
115
+ if (!EventMachine)
116
+ throw std::runtime_error ("not initialized");
117
+ return ConnectionDescriptor::SendDataToConnection (binding, data, data_length);
118
+ }
119
+
120
+
121
+ /*********************
122
+ evma_close_connection
123
+ *********************/
124
+
125
+ extern "C" void evma_close_connection (const char *binding, int after_writing)
126
+ {
127
+ if (!EventMachine)
128
+ throw std::runtime_error ("not initialized");
129
+ ConnectionDescriptor::CloseConnection (binding, (after_writing ? true : false));
130
+ }
131
+
132
+
133
+ /*****************
134
+ evma_stop_machine
135
+ *****************/
136
+
137
+ extern "C" void evma_stop_machine()
138
+ {
139
+ if (!EventMachine)
140
+ throw std::runtime_error ("not initialized");
141
+ EventMachine->ScheduleHalt();
142
+ }
143
+
144
+
145
+
146
+
@@ -0,0 +1,49 @@
1
+ /*****************************************************************************
2
+
3
+ $Id: eventmachine.h 2313 2006-04-15 16:12:57Z francis $
4
+
5
+ File: eventmachine.h
6
+ Date: 15Apr06
7
+
8
+ Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
9
+ Gmail: garbagecat10
10
+
11
+ This program is free software; you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License as published by
13
+ the Free Software Foundation; either version 2 of the License, or
14
+ (at your option) any later version.
15
+
16
+ This program is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License
22
+ along with this program; if not, write to the Free Software
23
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
+
25
+ *****************************************************************************/
26
+
27
+ #ifndef __EVMA_EventMachine__H_
28
+ #define __EVMA_EventMachine__H_
29
+
30
+ #if __cplusplus
31
+ extern "C" {
32
+ #endif
33
+
34
+ void evma_initialize_library (void(*)(const char*, int, const char*, int));
35
+ void evma_run_machine();
36
+ void evma_release_library();
37
+ const char *evma_install_oneshot_timer (int seconds);
38
+ const char *evma_connect_to_server (const char *server, int port);
39
+ const char *evma_create_tcp_server (const char *address, int port);
40
+ int evma_send_data_to_connection (const char *binding, const char *data, int data_length);
41
+ void evma_close_connection (const char *binding, int after_writing);
42
+ void evma_stop_machine();
43
+ #if __cplusplus
44
+ }
45
+ #endif
46
+
47
+
48
+ #endif // __EventMachine__H_
49
+
@@ -1,4 +1,4 @@
1
- # $Id: extconf.rb 2291 2006-04-14 03:56:18Z francis $
1
+ # $Id: extconf.rb 2328 2006-04-19 16:31:45Z francis $
2
2
  #
3
3
  #----------------------------------------------------------------------------
4
4
  #
@@ -28,4 +28,5 @@
28
28
 
29
29
  require 'mkmf'
30
30
  CONFIG['LDSHARED'] = "$(CXX) -shared"
31
- create_makefile "libeventmachine"
31
+ $LOCAL_LIBS << "-lpthread"
32
+ create_makefile "rubyeventmachine"
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: libmain.cpp 2291 2006-04-14 03:56:18Z francis $
3
+ $Id: libmain.cpp 2309 2006-04-15 15:37:53Z francis $
4
4
 
5
5
  File: libmain.cpp
6
6
  Date: 06Apr06
@@ -26,149 +26,126 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
26
 
27
27
  #include <ruby.h>
28
28
  #include "project.h"
29
+ #include "eventmachine.h"
29
30
 
30
31
 
31
- static EventMachine_t *EventMachine;
32
32
 
33
+ /*******
34
+ Statics
35
+ *******/
33
36
 
34
- /******************
35
- initialize_library
36
- ******************/
37
-
38
- extern "C" void initialize_library (void(*cb)(const char*, int, const char*, int))
39
- {
40
- InstallSignalHandlers();
41
- if (EventMachine)
42
- throw std::runtime_error ("already initialized");
43
- EventMachine = new EventMachine_t (cb);
44
- }
45
-
46
-
47
- /***************
48
- release_library
49
- ***************/
50
-
51
- extern "C" void release_library()
52
- {
53
- if (!EventMachine)
54
- throw std::runtime_error ("not initialized");
55
- delete EventMachine;
56
- EventMachine = NULL;
57
- }
58
-
59
-
60
- /***********
61
- run_machine
62
- ***********/
63
-
64
- extern "C" void run_machine()
65
- {
66
- if (!EventMachine)
67
- throw std::runtime_error ("not initialized");
68
- EventMachine->Run();
69
- }
70
-
71
-
72
- /*********************
73
- install_oneshot_timer
74
- *********************/
75
-
76
- extern "C" const char *install_oneshot_timer (int seconds)
77
- {
78
- if (!EventMachine)
79
- throw std::runtime_error ("not initialized");
80
- return EventMachine->InstallOneshotTimer (seconds);
81
- }
82
-
83
-
84
- /*****************
85
- connect_to_server
86
- *****************/
87
-
88
- extern "C" const char *connect_to_server (const char *server, int port)
89
- {
90
- if (!EventMachine)
91
- throw std::runtime_error ("not initialized");
92
- return EventMachine->ConnectToServer (server, port);
93
- }
94
-
95
-
96
- /*****************
97
- create_tcp_server
98
- *****************/
99
-
100
- extern "C" const char *create_tcp_server (const char *address, int port)
101
- {
102
- if (!EventMachine)
103
- throw std::runtime_error ("not initialized");
104
- return EventMachine->CreateTcpServer (address, port);
105
- }
106
-
37
+ static VALUE EmModule;
38
+ static int SyncSockets [2];
39
+ static bool UseThreads;
107
40
 
108
- /***********************
109
- send_data_to_connection
110
- ***********************/
41
+ static const char *A1;
42
+ static int A2;
43
+ static const char *A3;
44
+ static int A4;
111
45
 
112
- extern "C" int send_data_to_connection (const char *binding, const char *data, int data_length)
113
- {
114
- if (!EventMachine)
115
- throw std::runtime_error ("not initialized");
116
- return ConnectionDescriptor::SendDataToConnection (binding, data, data_length);
117
- }
118
46
 
119
47
 
120
48
  /****************
121
- close_connection
49
+ t_event_callback
122
50
  ****************/
123
51
 
124
- extern "C" void close_connection (const char *binding, int after_writing)
52
+ static void event_callback (const char *a1, int a2, const char *a3, int a4)
125
53
  {
126
- if (!EventMachine)
127
- throw std::runtime_error ("not initialized");
128
- ConnectionDescriptor::CloseConnection (binding, (after_writing ? true : false));
54
+ if (UseThreads) {
55
+ A1 = a1; A2 = a2; A3 = a3; A4 = a4;
56
+ write (SyncSockets[1], "+", 1);
57
+ char g;
58
+ read (SyncSockets[1], &g, 1);
59
+ }
60
+ else {
61
+ rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4));
62
+ }
129
63
  }
130
64
 
131
65
 
66
+ /********
67
+ TRunEvma
68
+ ********/
132
69
 
133
-
134
- /*******
135
- Statics
136
- *******/
137
-
138
- static VALUE EmModule;
139
-
140
- /****************
141
- t_event_callback
142
- ****************/
143
-
144
- static void event_callback (const char *a1, int a2, const char *a3, int a4)
70
+ void *TRunEvma (void *v)
145
71
  {
146
- rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4));
72
+ evma_run_machine();
73
+ write (SyncSockets[1], "$", 1);
147
74
  }
148
75
 
76
+
149
77
  /**************************
150
78
  t_initialize_event_machine
151
79
  **************************/
152
80
 
153
81
  static VALUE t_initialize_event_machine (VALUE self)
154
82
  {
155
- InstallSignalHandlers();
156
- if (EventMachine)
157
- rb_raise (rb_eRuntimeError, "event-machine already initialized");
158
- EventMachine = new EventMachine_t (event_callback);
83
+ evma_initialize_library (event_callback);
159
84
  return Qnil;
160
85
  }
161
86
 
162
87
 
88
+
89
+ /*************
90
+ t_run_machine_without_threads
91
+ *************/
92
+
93
+ static VALUE t_run_machine_without_threads (VALUE self)
94
+ {
95
+ UseThreads = false;
96
+ evma_run_machine();
97
+ }
98
+
99
+
163
100
  /*************
164
101
  t_run_machine
165
102
  *************/
166
103
 
167
104
  static VALUE t_run_machine (VALUE self)
168
105
  {
169
- if (!EventMachine)
170
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
171
- EventMachine->Run();
106
+ UseThreads = true;
107
+
108
+ int sp = socketpair (AF_LOCAL, SOCK_STREAM, 0, SyncSockets);
109
+ if (sp)
110
+ throw std::runtime_error ("no socket pair");
111
+
112
+ char buf [100];
113
+ snprintf (buf, sizeof(buf), "@io________pipe = IO.new( %d, \"r\")", SyncSockets[0]);
114
+ rb_eval_string (buf);
115
+
116
+ pthread_t tid;
117
+ pthread_create (&tid, NULL, TRunEvma, NULL);
118
+
119
+ while (true) {
120
+ VALUE v = rb_eval_string ("\
121
+ if s=select([@io________pipe]) and s=s.shift and s=s.shift\n\
122
+ r = s.read(1)\n\
123
+ if r == '+'\n\
124
+ 1\n\
125
+ elsif r == '$'\n\
126
+ 2\n\
127
+ else\n\
128
+ 0\n\
129
+ end\n\
130
+ else\n\
131
+ 0\n\
132
+ end\n\
133
+ ");
134
+
135
+ if (v == 3) {
136
+ rb_funcall (EmModule, rb_intern ("event_callback"), 3, rb_str_new2(A1), (A2 << 1) | 1, rb_str_new(A3,A4));
137
+ write (SyncSockets[0], "", 1);
138
+ }
139
+ else if (v == 5) {
140
+ break;
141
+ }
142
+
143
+ }
144
+
145
+ pthread_join (tid, NULL);
146
+ close (SyncSockets[0]);
147
+ close (SyncSockets[1]);
148
+
172
149
  return Qnil;
173
150
  }
174
151
 
@@ -179,9 +156,7 @@ t_add_oneshot_timer
179
156
 
180
157
  static VALUE t_add_oneshot_timer (VALUE self, VALUE interval)
181
158
  {
182
- if (!EventMachine)
183
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
184
- const char *f = EventMachine->InstallOneshotTimer (FIX2INT (interval));
159
+ const char *f = evma_install_oneshot_timer (FIX2INT (interval));
185
160
  if (!f || !*f)
186
161
  rb_raise (rb_eRuntimeError, "no timer");
187
162
  return rb_str_new2 (f);
@@ -194,9 +169,7 @@ t_start_server
194
169
 
195
170
  static VALUE t_start_server (VALUE self, VALUE server, VALUE port)
196
171
  {
197
- if (!EventMachine)
198
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
199
- const char *f = EventMachine->CreateTcpServer (StringValuePtr(server), FIX2INT(port));
172
+ const char *f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
200
173
  if (!f || !*f)
201
174
  rb_raise (rb_eRuntimeError, "no acceptor");
202
175
  return rb_str_new2 (f);
@@ -210,9 +183,7 @@ t_send_data
210
183
 
211
184
  static VALUE t_send_data (VALUE self, VALUE signature, VALUE data, VALUE data_length)
212
185
  {
213
- if (!EventMachine)
214
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
215
- int b = ConnectionDescriptor::SendDataToConnection (StringValuePtr (signature), StringValuePtr (data), FIX2INT (data_length));
186
+ int b = evma_send_data_to_connection (StringValuePtr (signature), StringValuePtr (data), FIX2INT (data_length));
216
187
  return (b << 1) | 1;
217
188
  }
218
189
 
@@ -223,9 +194,7 @@ t_close_connection
223
194
 
224
195
  static VALUE t_close_connection (VALUE self, VALUE signature, VALUE after_writing)
225
196
  {
226
- if (!EventMachine)
227
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
228
- ConnectionDescriptor::CloseConnection (StringValuePtr(signature), ((after_writing == Qtrue) ? true : false));
197
+ evma_close_connection (StringValuePtr (signature), ((after_writing == Qtrue) ? 1 : 0));
229
198
  return Qnil;
230
199
  }
231
200
 
@@ -237,9 +206,7 @@ t_connect_server
237
206
 
238
207
  static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
239
208
  {
240
- if (!EventMachine)
241
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
242
- const char *f = EventMachine->ConnectToServer (StringValuePtr(server), FIX2INT(port));
209
+ const char *f = evma_connect_to_server (StringValuePtr(server), FIX2INT(port));
243
210
  if (!f || !*f)
244
211
  rb_raise (rb_eRuntimeError, "no connection");
245
212
  return rb_str_new2 (f);
@@ -253,13 +220,7 @@ t_release_machine
253
220
 
254
221
  static VALUE t_release_machine (VALUE self)
255
222
  {
256
- if (!EventMachine)
257
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
258
- delete EventMachine;
259
- EventMachine = NULL;
260
- // ff line is a mistake, removed 11Apr06. EmModule is set permanently
261
- // for the process when we create the EventMachine module in Init_libeventmachine.
262
- //EmModule = Qnil;
223
+ evma_release_library();
263
224
  return Qnil;
264
225
  }
265
226
 
@@ -270,24 +231,23 @@ t_stop
270
231
 
271
232
  static VALUE t_stop (VALUE self)
272
233
  {
273
- if (!EventMachine)
274
- rb_raise (rb_eRuntimeError, "event-machine not initialized");
275
- EventMachine->ScheduleHalt();
276
- return Qnil;
234
+ evma_stop_machine();
235
+ return Qnil;
277
236
  }
278
237
 
279
238
 
280
239
 
281
- /********************
282
- Init_libeventmachine
283
- ********************/
240
+ /*********************
241
+ Init_rubyeventmachine
242
+ *********************/
284
243
 
285
- extern "C" void Init_libeventmachine()
244
+ extern "C" void Init_rubyeventmachine()
286
245
  {
287
246
  // INCOMPLETE, we need to define class Connectons inside module EventMachine
288
247
  EmModule = rb_define_module ("EventMachine");
289
248
  rb_define_module_function (EmModule, "initialize_event_machine", (VALUE(*)(...))t_initialize_event_machine, 0);
290
249
  rb_define_module_function (EmModule, "run_machine", (VALUE(*)(...))t_run_machine, 0);
250
+ rb_define_module_function (EmModule, "run_machine_without_threads", (VALUE(*)(...))t_run_machine_without_threads, 0);
291
251
  rb_define_module_function (EmModule, "add_oneshot_timer", (VALUE(*)(...))t_add_oneshot_timer, 1);
292
252
  rb_define_module_function (EmModule, "start_tcp_server", (VALUE(*)(...))t_start_server, 2);
293
253
  rb_define_module_function (EmModule, "send_data", (VALUE(*)(...))t_send_data, 3);
@@ -1,4 +1,4 @@
1
- # $Id: eventmachine.rb 2289 2006-04-14 03:52:22Z francis $
1
+ # $Id: eventmachine.rb 2325 2006-04-19 16:10:00Z francis $
2
2
  #
3
3
  # Author:: blackhedd (gmail address: garbagecat20).
4
4
  # Date:: 8 Apr 2006
@@ -34,7 +34,7 @@
34
34
  #
35
35
  #
36
36
 
37
- require 'libeventmachine'
37
+ require 'rubyeventmachine'
38
38
 
39
39
  # == Introduction
40
40
  # EventMachine provides a fast, lightweight framework for implementing
@@ -164,16 +164,20 @@ module EventMachine
164
164
  # See the description of stop_event_loop for an extremely simple client example.
165
165
  #
166
166
 
167
- def EventMachine::run &block
167
+ def EventMachine::run use_threads = true, &block
168
168
  @conns = {}
169
169
  @acceptors = {}
170
170
  @timers = {}
171
171
  initialize_event_machine
172
172
  block and add_timer 0, block
173
- run_machine
173
+ use_threads ? run_machine : run_machine_without_threads
174
174
  release_machine
175
175
  end
176
176
 
177
+ def EventMachine::run_without_threads &block
178
+ EventMachine::run false, &block
179
+ end
180
+
177
181
  # EventMachine#add_timer adds a one-shot timer to the event loop.
178
182
  # Call it with one or two parameters. The first parameters is a delay-time
179
183
  # expressed in <i>seconds</i> (not milliseconds). The second parameter, if
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: eventmachine
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.0
7
- date: 2006-04-14 00:00:00 -04:00
6
+ version: 0.4.2
7
+ date: 2006-04-19
8
8
  summary: Ruby/EventMachine socket engine library
9
9
  require_paths:
10
10
  - lib
@@ -13,7 +13,7 @@ email: garbagecat10@gmail.com
13
13
  homepage: http://rubyforge.org/projects/eventmachine
14
14
  rubyforge_project:
15
15
  description:
16
- autorequire: eventmachine
16
+ autorequire:
17
17
  default_executable:
18
18
  bindir: bin
19
19
  has_rdoc: true
@@ -25,23 +25,23 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
25
25
  version: 0.0.0
26
26
  version:
27
27
  platform: ruby
28
- signing_key:
29
- cert_chain:
30
28
  authors: []
31
29
  files:
32
30
  - tests/testem.rb
33
31
  - lib/eventmachine.rb
32
+ - ext/binder.cpp
33
+ - ext/rubymain.cpp
34
34
  - ext/sigs.h
35
- - ext/project.h
36
35
  - ext/sigs.cpp
37
- - ext/binder.cpp
38
- - ext/extconf.rb
39
- - ext/em.cpp
40
- - ext/binder.h
41
36
  - ext/ed.h
42
- - ext/ed.cpp
43
37
  - ext/em.h
44
- - ext/libmain.cpp
38
+ - ext/cmain.cpp
39
+ - ext/eventmachine.h
40
+ - ext/ed.cpp
41
+ - ext/binder.h
42
+ - ext/em.cpp
43
+ - ext/extconf.rb
44
+ - ext/project.h
45
45
  - README
46
46
  - RELEASE_NOTES
47
47
  - COPYING