File: nsv-commands.html

package info (click to toggle)
aolserver4 4.5.1-15.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 11,772 kB
  • sloc: ansic: 45,120; tcl: 5,532; sh: 1,021; makefile: 380; pascal: 219; php: 13
file content (353 lines) | stat: -rw-r--r-- 5,809 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
<html>
<head>
<title>AOLserver</title>
</head>
<body>

<h1>AOLserver nsv Commands</h1>

The nsv commands provide a high performance data sharing mechanism.
This facility is much flexible alternative to the obsolete ns_share
command.  The model uses an array syntax and includes more features.
In addition, lock contention is managed in a much more scalable
way--something that is not possible with the obsolete ns_share
facility.

<p>

<font color=red><b>NOTE: The use of ns_share is deprecated.  Careless
use of ns_share commands can severely limit the scalability of an
application.  The nsv commands solve this and this document describes
how to migrate your ns_share code to use nsv.</b></font>

<p>


<h2>Basics</h2>

<p>

The following commands currently make up the nsv interface:

<p>

    	nsv_get - get key value 
<br>
    	nsv_exists - check key existence
<br>
    	nsv_set - set key value
<br>
    	nsv_append - append value
<br>
    	nsv_lappend - append value as list element
<br>
    	nsv_incr - increment and return value
<br>
    	nsv_unset - unset a value
<br>
    	nsv_array - manage nsv arrays
<br>

<p>

Commands for the most part mirror the cooresponding Tcl command for
ordinary variables.  Basically, to set a value, simply use the nsv_set
command:

<p>

	nsv_set myarray foo $value

<p>

and to get a value, simply use the nsv_get command:

<p>

	set value [nsv_get myarray foo]

<p>



<p>

<h2>Migrating From ns_share</h2>

<p>

Migrating from ns_share is straightforward.  If your init.tcl included
commands such as:

<p>

	ns_share myshare
<br>
	set myshare(lock) [ns_mutex create]

<p>

use instead:

<p>

	nsv_set myshare lock [ns_mutex create]

<p>

In your procedures, instead of:

<p>

	proc myproc {} {
		ns_share myshare

<p>

		ns_mutex lock $myshare(lock)
		...

<p>

use:

<p>

	proc myproc {} {
<br>
		ns_mutex lock [nsv_get myshare lock]
<br>
		...

<p>

and within an ADP page, instead of:

<p>

	&lt;%
<br>
	ns_share myshare
<br>
	ns_puts $myshare(key1)
<br>
	%&gt;

<p>

	&lt;%=$myshare(key2)%&gt;

<p>

use:

<p>

	&lt;%
<br>
	ns_puts [nsv_get myshare key1]
<br>
	%&gt;

<p>

	&lt;%=[nsv_get myshare key2]%&gt;

<p>


Notice that, unlike ns_share, no command is required to define the
shared array.  The first attempt at setting the variable through any
means will automaticaly create the array.  Also notice that only arrays
are supported.  However, to migrate from ns_share you can simply package
up all existing ns_share scalars into a single array with a short name,
perhaps just ".". For example, if you had:

<p>

	ns_share mylock myfile
<br>
	set myfile /tmp/some.file
<br>
	set mylock [ns_mutex create]

<p>

you can use:

<p>

	nsv_set . myfile /tmp/some.file
<br>
	nsv_set . mylock [ns_mutex create]

<p>


<h2>Multithreading Features</h2>

<p>

One advantages of nsv is built in interlocking for thread safety.
For example, consider a case of a "increment-by-one" unique id system.
Here's the ns_share solution:

<p>

	ns_share ids
<br>
	set ids(lock) [ns_mutex create]
<br>
	set ids(next) 0

<p>

	proc nextid {} {
<br>
		ns_share ids
<br>
		ns_mutex lock $ids(lock)
<br>
		set next [incr ids(next)]
<br>
		ns_mutex unlock $ids(lock)
<br>
		return $next
<br>
	}

<p>

and here's an nsv solution:

<p>

	nsv_set ids next 0

<p>

	proc nextid {} {
<br>
		return [nsv_incr ids next]
<br>
	}

<p>

Note that the nsv solution does not need a mutex as the nsv_incr command
is internally interlocked.

<p>


<h2>Compatibility with Tcl Arrays</h2>

<p>

Another useful feature of nsv is the nsv_array command which works much
like the Tcl array command.  This can be used to import and export values
from ordinary Tcl arrays.  For example, to copy from Tcl use:

<p>

	nsv_array set meta [array get tmpmeta]

<p>

and to copy to Tcl use:

<p>

	array set metacopy [nsv_array get meta]

<p>

As with all other nsv command, nsv_array is atomic and no explicit
locking is required.  This feature can be used to contruct a new nsv
array by first filling up an ordinary temporary Tcl array via some time
consuming process and then swapping it into place as above.  While the
new temporary array is being constructed, other threads can access the
old array without delay or inconsistant data.  You can even reset a
complete nsv array in one step with "reset".  For example, instead of:

<p>

	ns_share lock meta
<br>
	set lock [ns_mutex create]

<p>

	ns_mutex lock $lock
<br>
	unset meta
<br>
	array set meta [array get tmpmeta]
<br>
	ns_mutex unlock $lock

<p>

you can simply use:

<p>

	nsv_array reset meta [array get tmpmeta]

<p>

The reset option will flush and then reset all values atomically,
eliminating the need for the explicit lock.

<p>

Other options for the nsv_array command include:

<p>

	nsv_exists array - test existance of array
<br>
	nsv_size array - return # of elements in array
<br>
	nsv_names array - return keys of array

<p>


<h2>Configuration</h2>

<p>

The nsv system uses a common multithreading technique to reduce the
potential for lock contention which is to split the locks to acheive
finer grained locking.  This technique groups arrays randomly into
buckets and only the arrays within a particular bucket share a lock.
The number of buckets to be used can be configured by setting the
"nsvbuckets" tcl parameters, e.g.:

<p>

	[ns/server/server1/tcl]
<br>
	nsvbuckets=20

<p>

The default is 8 which should be reasonalbe.  Note that you can monitor
the lock contention, if any, by enabling mutex metering:

<p>

	[ns/threads]
<br>
	mutexmetering=on

<p>

and then viewing the results of "ns_info locks" command after the server
has been running for some time.  The nsv locks all have names of the
form "nsv:##".  If you find many lock attempts which did not successed
immediately, try increasing nsvbuckets.

</body>
</html>