@@ -60,13 +60,25 @@ var DirectoryStore = exports.DirectoryStore = function (location) {
60
60
// Our cache of already created namespaces
61
61
if ( validNamespaces . hasOwnProperty ( namespace ) ) {
62
62
return true ;
63
- } else {
64
63
}
65
64
66
65
var namespacePath = path . join ( location , sha1 . hex_sha1 ( namespace ) ) ;
67
-
66
+ var nameFile = namespacePath + ".namespace" ;
67
+ var p ;
68
+
68
69
// TODO: rewrite to use promises
69
70
try {
71
+ try {
72
+ nameStats = posix . stat ( nameFile ) . wait ( ) ;
73
+ } catch ( e ) {
74
+ if ( e . message !== "No such file or directory" ) {
75
+ throw e ;
76
+ } else {
77
+ p = atomicWrite ( nameFile , JSON . stringify ( namespace ) , 0600 ) ;
78
+ p . wait ( ) ;
79
+ }
80
+ }
81
+
70
82
stats = posix . stat ( namespacePath ) . wait ( ) ;
71
83
72
84
if ( ! stats . isDirectory ( ) ) {
@@ -134,21 +146,20 @@ var DirectoryStore = exports.DirectoryStore = function (location) {
134
146
*/
135
147
var unset = function ( namespace , key ) {
136
148
var filename = valuePath ( namespace , key ) ;
149
+ var key_filename = filename + ".key" ;
150
+ posix . unlink ( key_filename ) ;
137
151
return posix . unlink ( filename ) ;
138
152
}
139
153
this . unset = unset ;
140
154
141
- /* set(namespace, key, value)
142
- *
143
- * Save a value to the directory store indexed by namespace and key.
144
- * Both namespace and key SHOULD be strings. value can be any value that
145
- * can be serialized by JSON.stringify.
146
- */
147
- var set = function ( namespace , key , value ) {
148
- assertNamespace ( namespace ) ;
155
+ var atomicWrite = function ( filename , value , mode ) {
156
+ if ( typeof value !== "string" ) {
157
+ throw {
158
+ message : "Value must be a string"
159
+ }
160
+ }
149
161
150
162
var p = new events . Promise ( ) ;
151
- var filename = valuePath ( namespace , key ) ;
152
163
153
164
/* Create a proper temp filename */
154
165
var date = new Date ( ) ;
@@ -158,10 +169,10 @@ var DirectoryStore = exports.DirectoryStore = function (location) {
158
169
var filenameTmp = filename + "." + tmp + ".tmp" ;
159
170
160
171
var openPromise = posix . open ( filenameTmp ,
161
- process . O_CREAT | process . O_WRONLY , 0600 ) ;
172
+ process . O_CREAT | process . O_WRONLY , mode ) ;
162
173
163
174
openPromise . addCallback ( function ( fd ) {
164
- var writePromise = posix . write ( fd , JSON . stringify ( value ) ) ;
175
+ var writePromise = posix . write ( fd , value ) ;
165
176
writePromise . addCallback ( function ( written ) {
166
177
var closePromise = posix . close ( fd ) ;
167
178
closePromise . addCallback ( function ( ) {
@@ -203,10 +214,53 @@ var DirectoryStore = exports.DirectoryStore = function (location) {
203
214
p . emitError ( e ) ;
204
215
} ) ;
205
216
217
+ return p ;
218
+ }
219
+
220
+ /* set(namespace, key, value)
221
+ *
222
+ * Save a value to the directory store indexed by namespace and key.
223
+ * Both namespace and key SHOULD be strings. value can be any value that
224
+ * can be serialized by JSON.stringify.
225
+ */
226
+ var set = function ( namespace , key , value ) {
227
+ assertNamespace ( namespace ) ;
228
+ var filename = valuePath ( namespace , key ) ;
229
+ var key_filename = filename + ".key" ;
230
+
231
+ var p = new events . Promise ( ) ;
232
+
233
+ var keyPromise = atomicWrite ( key_filename , JSON . stringify ( key ) , 0600 ) ;
234
+ keyPromise . addCallback ( function ( ) {
235
+ var writePromise = atomicWrite ( filename , JSON . stringify ( value ) , 0600 ) ;
236
+ writePromise . addCallback ( function ( ) {
237
+ p . emitSuccess ( ) ;
238
+ } ) ;
239
+ writePromise . addErrback ( function ( e ) {
240
+ p . emitError ( e ) ;
241
+ } ) ;
242
+ } ) ;
243
+ keyPromise . addErrback ( function ( e ) {
244
+ p . emitError ( e ) ;
245
+ } ) ;
246
+
206
247
return p ;
207
248
} ;
208
249
this . set = set ;
209
250
251
+
252
+
253
+ /* close()
254
+ *
255
+ * This is a NOOP in DirectoryStore, but may be useful for other types of
256
+ * data stores.
257
+ */
258
+ var close = function ( ) {
259
+ /* we need to do something; we'll stat the readme file. */
260
+ return posix . stat ( readmePath ) ;
261
+ } ;
262
+ this . close = close ;
263
+
210
264
// If the file exists, make sure that it is a directory and that it
211
265
// writable.
212
266
try {
0 commit comments