solaris-kstat 1.0.3 → 1.1.0
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/CHANGES +7 -0
- data/MANIFEST +4 -3
- data/README +44 -49
- data/Rakefile +33 -27
- data/lib/solaris/kstat.rb +321 -0
- data/lib/solaris/kstat/functions.rb +22 -0
- data/lib/solaris/kstat/structs.rb +260 -0
- data/solaris-kstat.gemspec +7 -5
- data/test/test_solaris_kstat.rb +91 -57
- data/test/test_solaris_kstat_structs.rb +60 -0
- metadata +93 -55
- data/ext/extconf.rb +0 -15
- data/ext/solaris/rkstat.c +0 -240
- data/ext/solaris/rkstat.h +0 -353
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'test-unit'
|
2
|
+
require 'mkmf/lite'
|
3
|
+
require 'solaris/kstat/structs'
|
4
|
+
|
5
|
+
class StructTest < Test::Unit::TestCase
|
6
|
+
include Mkmf::Lite
|
7
|
+
include Solaris::Structs
|
8
|
+
|
9
|
+
test "KstatCtl struct is the proper size" do
|
10
|
+
assert_equal(KstatCtl.size, check_sizeof('kstat_ctl_t', 'kstat.h'))
|
11
|
+
end
|
12
|
+
|
13
|
+
test "KstatStruct struct is the proper size" do
|
14
|
+
assert_equal(KstatStruct.size, check_sizeof('kstat_t', 'kstat.h'))
|
15
|
+
end
|
16
|
+
|
17
|
+
test "KstatNamed struct is the proper size" do
|
18
|
+
assert_equal(KstatNamed.size, check_sizeof('kstat_named_t', 'kstat.h'))
|
19
|
+
end
|
20
|
+
|
21
|
+
test "Vminfo struct is the proper size" do
|
22
|
+
assert_equal(Vminfo.size, check_sizeof('vminfo_t', 'sys/sysinfo.h'))
|
23
|
+
end
|
24
|
+
|
25
|
+
test "Flushmeter struct is the proper size" do
|
26
|
+
assert_equal(Flushmeter.size, check_sizeof('struct flushmeter', 'sys/vmmeter.h'))
|
27
|
+
end
|
28
|
+
|
29
|
+
#test "NcStats struct is the proper size" do
|
30
|
+
# assert_equal(NcStats.size, check_sizeof('struct nc_stats', 'sys/dnlc.h'))
|
31
|
+
#end
|
32
|
+
|
33
|
+
test "Sysinfo struct is the proper size" do
|
34
|
+
assert_equal(Sysinfo.size, check_sizeof('sysinfo_t', 'sys/sysinfo.h'))
|
35
|
+
end
|
36
|
+
|
37
|
+
test "Var struct is the proper size" do
|
38
|
+
assert_equal(Var.size, check_sizeof('struct var', 'sys/var.h'))
|
39
|
+
end
|
40
|
+
|
41
|
+
test "KstatIntr struct is the proper size" do
|
42
|
+
assert_equal(KstatIntr.size, check_sizeof('kstat_intr_t', 'sys/kstat.h'))
|
43
|
+
end
|
44
|
+
|
45
|
+
test "KstatIo struct is the proper size" do
|
46
|
+
assert_equal(KstatIo.size, check_sizeof('kstat_io_t', 'sys/kstat.h'))
|
47
|
+
end
|
48
|
+
|
49
|
+
test "KstatTimer struct is the proper size" do
|
50
|
+
assert_equal(KstatTimer.size, check_sizeof('kstat_timer_t', 'sys/kstat.h'))
|
51
|
+
end
|
52
|
+
|
53
|
+
test "CpuSysinfo struct is the proper size" do
|
54
|
+
assert_equal(CpuSysinfo.size, check_sizeof('cpu_sysinfo_t', 'sys/sysinfo.h'))
|
55
|
+
end
|
56
|
+
|
57
|
+
#test "Mntinfo struct is the proper size" do
|
58
|
+
# assert_equal(Mntinfo.size, check_sizeof('struct mntinfo_kstat', 'nfs/nfs_clnt.h'))
|
59
|
+
#end
|
60
|
+
end
|
metadata
CHANGED
@@ -1,90 +1,128 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: solaris-kstat
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 3
|
10
|
-
version: 1.0.3
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Daniel J. Berger
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
date: 2013-10-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ffi
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
21
31
|
name: test-unit
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mkmf-lite
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
22
55
|
prerelease: false
|
23
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
57
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
32
70
|
type: :development
|
33
|
-
|
34
|
-
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: ! " The solaris-kstat library provides a Ruby interface for gathering
|
79
|
+
kernel\n statistics from the Solaris operating system. Each matching statistic
|
80
|
+
is\n provided with its module, instance, and name fields, as well as its actual\n
|
81
|
+
\ value.\n"
|
35
82
|
email: djberg96@gmail.com
|
36
83
|
executables: []
|
37
|
-
|
38
|
-
|
39
|
-
- ext/extconf.rb
|
40
|
-
extra_rdoc_files:
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files:
|
41
86
|
- README
|
42
87
|
- CHANGES
|
43
88
|
- MANIFEST
|
44
|
-
|
45
|
-
files:
|
89
|
+
files:
|
46
90
|
- CHANGES
|
47
91
|
- MANIFEST
|
48
92
|
- README
|
49
93
|
- Rakefile
|
50
94
|
- examples/example_kstat.rb
|
51
|
-
- ext/extconf.rb
|
52
|
-
- ext/solaris/rkstat.c
|
53
|
-
- ext/solaris/rkstat.h
|
54
95
|
- solaris-kstat.gemspec
|
55
96
|
- test/test_solaris_kstat.rb
|
56
|
-
|
57
|
-
|
97
|
+
- test/test_solaris_kstat_structs.rb
|
98
|
+
- lib/solaris/kstat.rb
|
99
|
+
- lib/solaris/kstat/functions.rb
|
100
|
+
- lib/solaris/kstat/structs.rb
|
101
|
+
homepage: https://github.com/djberg96/solaris-kstat
|
102
|
+
licenses:
|
58
103
|
- Artistic 2.0
|
59
104
|
post_install_message:
|
60
105
|
rdoc_options: []
|
61
|
-
|
62
|
-
require_paths:
|
106
|
+
require_paths:
|
63
107
|
- lib
|
64
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
109
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
|
71
|
-
- 0
|
72
|
-
version: "0"
|
73
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
115
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
segments:
|
80
|
-
- 0
|
81
|
-
version: "0"
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
82
120
|
requirements: []
|
83
|
-
|
84
121
|
rubyforge_project: solarisutils
|
85
|
-
rubygems_version: 1.8.
|
122
|
+
rubygems_version: 1.8.24
|
86
123
|
signing_key:
|
87
124
|
specification_version: 3
|
88
125
|
summary: Interface for the Solaris kstat library
|
89
|
-
test_files:
|
126
|
+
test_files:
|
90
127
|
- test/test_solaris_kstat.rb
|
128
|
+
- test/test_solaris_kstat_structs.rb
|
data/ext/extconf.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
dir_config('kstat')
|
5
|
-
|
6
|
-
# This package requires Solaris 2.8 or later
|
7
|
-
unless have_header('kstat.h')
|
8
|
-
STDERR.puts "The kstat.h header file was not found. Exiting."
|
9
|
-
exit
|
10
|
-
end
|
11
|
-
|
12
|
-
$INCFLAGS += " -Isolaris"
|
13
|
-
|
14
|
-
have_library('kstat')
|
15
|
-
create_makefile('solaris/kstat', 'solaris')
|
data/ext/solaris/rkstat.c
DELETED
@@ -1,240 +0,0 @@
|
|
1
|
-
#ifdef __cplusplus
|
2
|
-
extern "C" {
|
3
|
-
#endif
|
4
|
-
|
5
|
-
#include <kstat.h>
|
6
|
-
#include <nfs/nfs.h>
|
7
|
-
#include <nfs/nfs_clnt.h>
|
8
|
-
#include <sys/utsname.h>
|
9
|
-
#include <sys/sysinfo.h>
|
10
|
-
#include <sys/inttypes.h>
|
11
|
-
#include <sys/dnlc.h>
|
12
|
-
#include <sys/vmmeter.h>
|
13
|
-
#include <sys/var.h>
|
14
|
-
#include <errno.h>
|
15
|
-
#include <string.h>
|
16
|
-
|
17
|
-
#include "ruby.h"
|
18
|
-
#include "rkstat.h"
|
19
|
-
|
20
|
-
VALUE cKstatError;
|
21
|
-
|
22
|
-
static VALUE ks_allocate(VALUE klass){
|
23
|
-
KstatStruct* ptr;
|
24
|
-
return Data_Make_Struct(klass, KstatStruct, 0, ks_free, ptr);
|
25
|
-
}
|
26
|
-
|
27
|
-
/*
|
28
|
-
* call-seq:
|
29
|
-
* Kstat.new(module=nil, instance=-1, name=nil)
|
30
|
-
*
|
31
|
-
* Creates and returns a Kstat object. This does NOT traverse the kstat
|
32
|
-
* chain. The Kstat#record method uses the values passed to actually
|
33
|
-
* retrieve data.
|
34
|
-
*
|
35
|
-
* You may specify a module, an instance and a name. The module defaults to
|
36
|
-
* nil (all modules), the instance defaults to -1 (all instances) and the
|
37
|
-
* name defaults to nil (all names).
|
38
|
-
*/
|
39
|
-
VALUE ks_init(int argc, VALUE* argv, VALUE self){
|
40
|
-
KstatStruct* ptr;
|
41
|
-
VALUE v_module, v_instance, v_name;
|
42
|
-
|
43
|
-
Data_Get_Struct(self,KstatStruct,ptr);
|
44
|
-
|
45
|
-
rb_scan_args(argc, argv, "03", &v_module, &v_instance, &v_name);
|
46
|
-
|
47
|
-
if(!NIL_P(v_module)){
|
48
|
-
SafeStringValue(v_module);
|
49
|
-
rb_iv_set(self, "@module", v_module);
|
50
|
-
}
|
51
|
-
else{
|
52
|
-
rb_iv_set(self, "@module", Qnil);
|
53
|
-
}
|
54
|
-
|
55
|
-
if(!NIL_P(v_name)){
|
56
|
-
SafeStringValue(v_name);
|
57
|
-
rb_iv_set(self, "@name", v_name);
|
58
|
-
}
|
59
|
-
else{
|
60
|
-
rb_iv_set(self, "@name", Qnil);
|
61
|
-
}
|
62
|
-
|
63
|
-
if(!NIL_P(v_instance))
|
64
|
-
rb_iv_set(self, "@instance", v_instance);
|
65
|
-
else
|
66
|
-
rb_iv_set(self, "@instance", Qnil);
|
67
|
-
|
68
|
-
return self;
|
69
|
-
}
|
70
|
-
|
71
|
-
/*
|
72
|
-
* Helper function ks_record which will either return an existing value for
|
73
|
-
* the given key, or assign that key a new empty hash if it has no value
|
74
|
-
* associated with it.
|
75
|
-
*/
|
76
|
-
VALUE get_hash_for_key(VALUE v_hash, VALUE v_key){
|
77
|
-
volatile VALUE v_new_hash;
|
78
|
-
|
79
|
-
v_new_hash = rb_hash_aref(v_hash, v_key);
|
80
|
-
|
81
|
-
if(NIL_P(v_new_hash)){
|
82
|
-
v_new_hash = rb_hash_new();
|
83
|
-
rb_hash_aset(v_hash, v_key, v_new_hash);
|
84
|
-
}
|
85
|
-
|
86
|
-
return v_new_hash;
|
87
|
-
}
|
88
|
-
|
89
|
-
/*
|
90
|
-
* Returns a nested hash based on the values passed to the constructor. How
|
91
|
-
* deeply that hash is nested depends on the values passed to the constructor.
|
92
|
-
* The more specific your criterion, the less data you will receive.
|
93
|
-
*/
|
94
|
-
VALUE ks_record(VALUE self){
|
95
|
-
volatile VALUE v_m_hash, v_i_hash, v_n_hash, v_s_hash;
|
96
|
-
KstatStruct* ptr;
|
97
|
-
kstat_io_t kio;
|
98
|
-
kstat_timer_t kt;
|
99
|
-
char* module;
|
100
|
-
char* name;
|
101
|
-
int instance = -1; // -1 represents all instances (the default)
|
102
|
-
|
103
|
-
VALUE v_module, v_instance, v_name;
|
104
|
-
|
105
|
-
Data_Get_Struct(self,KstatStruct,ptr);
|
106
|
-
|
107
|
-
v_m_hash = rb_hash_new(); // Module name is key, holds v_i_hashes
|
108
|
-
|
109
|
-
v_module = rb_iv_get(self, "@module");
|
110
|
-
v_instance = rb_iv_get(self, "@instance");
|
111
|
-
v_name = rb_iv_get(self, "@name");
|
112
|
-
|
113
|
-
// Module is NULL by default (i.e. all modules are returned)
|
114
|
-
if(NIL_P(v_module))
|
115
|
-
module = NULL;
|
116
|
-
else
|
117
|
-
module = StringValuePtr(v_module);
|
118
|
-
|
119
|
-
// Instance defaults to -1 (i.e. all instances are returned)
|
120
|
-
if(!NIL_P(v_instance))
|
121
|
-
instance = NUM2INT(v_instance);
|
122
|
-
|
123
|
-
// Name is NULL by default (i.e. all names are returned)
|
124
|
-
if(NIL_P(v_name))
|
125
|
-
name = NULL;
|
126
|
-
else
|
127
|
-
name = StringValuePtr(v_name);
|
128
|
-
|
129
|
-
// A failure probably means the module, instance or name doesn't exist
|
130
|
-
if((ptr->kc = kstat_open()) == NULL)
|
131
|
-
rb_raise(cKstatError, "kstat_open() failure: %s", strerror(errno));
|
132
|
-
|
133
|
-
/*
|
134
|
-
* Traverse the kstat chain, looking for matches based on supplied data.
|
135
|
-
* A failure likely means a non-existant module or name was provided.
|
136
|
-
*/
|
137
|
-
if((ptr->ksp = kstat_lookup(ptr->kc, module, instance, name)) == NULL)
|
138
|
-
rb_raise(cKstatError, "kstat_lookup() failure: %s", strerror(errno));
|
139
|
-
|
140
|
-
// Sync the chain with the kernel
|
141
|
-
if(kstat_chain_update(ptr->kc) == -1)
|
142
|
-
rb_raise(cKstatError, "kstat_chain_update() failure: %s", strerror(errno));
|
143
|
-
|
144
|
-
while(ptr->ksp){
|
145
|
-
// If a module is specified, ignore modules that don't match
|
146
|
-
if((module) && (strcmp(module,ptr->ksp->ks_module))){
|
147
|
-
ptr->ksp = ptr->ksp->ks_next;
|
148
|
-
continue;
|
149
|
-
}
|
150
|
-
|
151
|
-
// If an instance is specified, ignore instances that don't match
|
152
|
-
if((instance != -1) && (instance != ptr->ksp->ks_instance)){
|
153
|
-
ptr->ksp = ptr->ksp->ks_next;
|
154
|
-
continue;
|
155
|
-
}
|
156
|
-
|
157
|
-
// If a name is specified, ignore names that don't match
|
158
|
-
if((name) && (strcmp(name,ptr->ksp->ks_name))){
|
159
|
-
ptr->ksp = ptr->ksp->ks_next;
|
160
|
-
continue;
|
161
|
-
}
|
162
|
-
|
163
|
-
// Call the appropriate data mapper based on ks_type
|
164
|
-
switch(ptr->ksp->ks_type){
|
165
|
-
case KSTAT_TYPE_NAMED:
|
166
|
-
kstat_read(ptr->kc, ptr->ksp, NULL);
|
167
|
-
v_s_hash = map_named_data_type(ptr->ksp);
|
168
|
-
break;
|
169
|
-
case KSTAT_TYPE_IO:
|
170
|
-
kstat_read(ptr->kc, ptr->ksp, &kio);
|
171
|
-
v_s_hash = map_io_data_type(&kio);
|
172
|
-
break;
|
173
|
-
case KSTAT_TYPE_TIMER:
|
174
|
-
kstat_read(ptr->kc, ptr->ksp, &kt);
|
175
|
-
v_s_hash = map_timer_data_type(&kt);
|
176
|
-
break;
|
177
|
-
case KSTAT_TYPE_INTR:
|
178
|
-
kstat_read(ptr->kc, ptr->ksp, NULL);
|
179
|
-
v_s_hash = map_intr_data_type(ptr->ksp);
|
180
|
-
break;
|
181
|
-
case KSTAT_TYPE_RAW:
|
182
|
-
kstat_read(ptr->kc, ptr->ksp, NULL);
|
183
|
-
v_s_hash = map_raw_data_type(ptr->ksp);
|
184
|
-
break;
|
185
|
-
default:
|
186
|
-
rb_raise(cKstatError,"Unknown data record type");
|
187
|
-
}
|
188
|
-
|
189
|
-
/* Set the class for this set of statistics */
|
190
|
-
if(ptr->ksp->ks_class)
|
191
|
-
rb_hash_aset(v_s_hash, rb_str_new2("class"), rb_str_new2(ptr->ksp->ks_class));
|
192
|
-
|
193
|
-
v_i_hash = get_hash_for_key(v_m_hash, rb_str_new2(ptr->ksp->ks_module));
|
194
|
-
v_n_hash = get_hash_for_key(v_i_hash, INT2FIX(ptr->ksp->ks_instance));
|
195
|
-
|
196
|
-
rb_hash_aset(v_n_hash, rb_str_new2(ptr->ksp->ks_name), v_s_hash);
|
197
|
-
rb_hash_aset(v_i_hash, INT2FIX(ptr->ksp->ks_instance), v_n_hash);
|
198
|
-
rb_hash_aset(v_m_hash, rb_str_new2(ptr->ksp->ks_module), v_i_hash);
|
199
|
-
|
200
|
-
ptr->ksp = ptr->ksp->ks_next;
|
201
|
-
}
|
202
|
-
|
203
|
-
return v_m_hash;
|
204
|
-
}
|
205
|
-
|
206
|
-
void Init_kstat(){
|
207
|
-
VALUE mSolaris, cKstat;
|
208
|
-
|
209
|
-
/* The Solaris module only serves as a toplevel namespace */
|
210
|
-
mSolaris = rb_define_module("Solaris");
|
211
|
-
|
212
|
-
/* The Kstat class encapsulates kstat (kernel statistics) information */
|
213
|
-
cKstat = rb_define_class_under(mSolaris, "Kstat", rb_cObject);
|
214
|
-
|
215
|
-
/* The Kstat::Error class is raised if any of the Kstat methods fail */
|
216
|
-
cKstatError = rb_define_class_under(cKstat, "Error", rb_eStandardError);
|
217
|
-
|
218
|
-
rb_define_alloc_func(cKstat, ks_allocate);
|
219
|
-
|
220
|
-
// Instance Methods
|
221
|
-
|
222
|
-
rb_define_method(cKstat, "initialize", ks_init, -1);
|
223
|
-
rb_define_method(cKstat, "record", ks_record, 0);
|
224
|
-
|
225
|
-
// Kernel module
|
226
|
-
rb_define_attr(cKstat, "module", 1, 1);
|
227
|
-
|
228
|
-
// Index of module entity
|
229
|
-
rb_define_attr(cKstat, "instance", 1, 1);
|
230
|
-
|
231
|
-
// Unique name within module
|
232
|
-
rb_define_attr(cKstat, "name", 1, 1);
|
233
|
-
|
234
|
-
/* 1.0.3: The version of the solaris-kstat library */
|
235
|
-
rb_define_const(cKstat, "VERSION", rb_str_new2(SOLARIS_KSTAT_VERSION));
|
236
|
-
}
|
237
|
-
|
238
|
-
#ifdef __cplusplus
|
239
|
-
}
|
240
|
-
#endif
|