OSDN Git Service

[TMP] Initialize db for debugging /api/v1/execution
[eos/zephyr.git] / server / class / DB.js
1 /**
2  * DBを操作するクラス
3  *
4  * @returns {object}
5  */
6 'use strict';
7
8 var fs = require('fs');
9 var Sequelize = require('sequelize');
10 var co = require('co');
11 var uuid = require('node-uuid');
12
13 var sequelize;
14 var test = 'hello';
15 var Files; // Model object of sequelize
16
17  var instance = {
18     init: init,
19     sayHello: function() {
20         return test;
21     },
22     getDirectoryParentId: getDirectoryParentId,
23     getDirectoryId: getDirectoryId,
24     getDirectory: getDirectory,
25     existFile: existFile,
26     notExistFile: notExistFile,
27     existDirectory: existDirectory,
28     notExistDirectory: notExistDirectory,
29     createFile: createFile,
30     removeFile: removeFile,
31     createDirectory: createDirectory,
32     test1: test1,
33     test2: test2,
34     testRest: testRest
35     /*
36     removeDirectory: removeDirectory,
37     getFilename: getFilename,
38     moveFile: moveFile,
39     moveDirectory: moveDirectory
40     */
41 };
42
43 /**
44  * init
45  * @constructor
46  * @returns {promise}
47  */
48
49 /** 
50  * productionモード時は、db.workspaceを永続化させる
51  * DEBUGモードの時は、db.debugを実行毎に作成する。
52  * DEBUGモードの時は、sync()の中で、/レコードがFilesテーブルに追加される。
53  * モードの切り替えは環境変数NODE_ENVで行っている。
54  * zephyr serveコマンドが実行されるとNODE_ENV = 'production'
55  * zephyr debugコマンドが実行されるとNODE_ENV = 'debug'
56  * となる。
57  * それぞれの設定は$ZEOHYR_HOME/cli/zephyr-serve, $ZEPHYR_HOME/zephyre_debugを参照
58  */
59
60     function init() {
61         var dbPath;
62         var dbOption = {
63             dialect: 'sqlite'
64         };
65
66         if(process.env['NODE_ENV'] === 'production') {
67             dbPath = __dirname + '/../../user-specific-files/db/db.workspace';
68             // if doesn't exist workspace.db, create.
69             try {
70                 fs.accessSync(dbPath, fs.R_OK | fs.W_OK);
71             } catch(e) {
72                 fs.writeFileSync(dbPath, '');
73             }
74             dbOption.storage = dbPath;
75
76         } else if(process.env['NODE_ENV'] === 'debug') {
77             dbPath = __dirname + '/../../user-specific-files/db/db.debug';
78             try {
79                 fs.accessSync(dbPath, fs.R_OK | fs.W_OK);
80                 fs.unlinkSync(dbPath);
81             } catch(e) {
82             }
83
84             fs.writeFileSync(dbPath, '');
85             dbOption.storage = dbPath;
86         }
87
88         sequelize = new Sequelize('','','', dbOption);
89
90         Files = sequelize.define('file', {
91             fileId: {
92                 type: Sequelize.UUID,
93                 field: 'file_id',
94                 primaryKey: true
95             },
96             name: {
97                 type: Sequelize.STRING,
98                 field: 'name',
99                 allowNull: false
100             },
101             parentId: {
102                 type: Sequelize.UUID,
103                 field: 'parent_id',
104                 allowNull: false
105             },
106             fileType: {
107                 type: Sequelize.ENUM(0,1),
108                 field: 'file_type',
109                 allowNull: false
110             }
111         });
112
113         var force = process.env.NODE_ENV !== 'production';
114         return Files.sync({force: force})
115         .then(function() {
116             return insertRoot();
117         });
118     }
119
120
121 /**
122  * sync
123  *
124  * @returns {promise}<DBオブジェクトの関数群のオブジェクトをresolveする>
125  */
126 function insertRoot() {
127     return new Promise(function(resolve, reject) {
128         var q = {
129             where: {
130                 name: '/'
131             }
132         };
133         Files.findOne(q)
134         .then(function(r) {
135             if(r === null) {
136                 var root = {
137                     fileId: '1f83f620-c1ed-11e5-9657-7942989daa00', // rootのuuidは固定値
138                     name: '/',
139                     parentId: '',
140                     fileType: 0
141                 };
142                 return Files.create(root);
143             }
144         })
145         .then(function() {
146             resolve();
147         });
148     });
149 }
150
151 /**
152  * getDirectoryParentId
153  * ディレクトリのparentIdを取得する 
154  * @param name
155  * @returns {promise} ディレクトリが存在すればresolve(uuid), しなければreject
156  */
157 function getDirectoryParentId(name) {
158     return new Promise(function(resolve, reject) {
159         var q = {
160             where: {
161                 name: name,
162                 fileType: 0
163             }
164         };
165         Files.findAll(q)
166         .then(function(r) {
167             if(r.length === 0) {
168                 reject(new Error('"' + name + '" directory doesn\'t exist.'));
169             } else {
170                 var map = r.map(function(c) { return c.dataValues.parentId });
171                 resolve(map);
172             }
173         });
174     });
175 }
176
177
178 /**
179  * getDirectoryId
180  * ディレクトリのfileIdを取得する 
181  * @param name
182  * @returns {promise} ディレクトリが存在すればresolve(uuid), しなければreject
183  */
184
185 function getDirectoryId(name) {
186     return new Promise(function(resolve, reject) {
187         var q = {
188             where: {
189                 name: name,
190                 fileType: 0
191             }
192         };
193         Files.findAll(q)
194         .then(function(r) {
195             if(r.length === 0) {
196                 reject(new Error('"' + name + '" directory doesn\'t exist.'));
197             } else {
198                 var map = r.map(function(c) { return c.dataValues.fileId });
199                 resolve(map);
200             }
201         });
202     });
203 }
204
205 /**
206  * getDirectory
207  * ディレクトリのfileIdを取得する 
208  * @param name
209  * @returns {promise} ディレクトリが存在すればresolve(name), しなければreject
210  */
211
212 function getDirectory(name) {
213     return new Promise(function(resolve, reject) {
214         var q = {
215             where: {
216                 name: name,
217                 fileType: 0
218             }
219         };
220         Files.findAll(q)
221         .then(function(r) {
222             if(r.length === 0) {
223                 reject(new Error('"' + name + '" directory doesn\'t exist.'));
224             } else {
225                 var map = r.map(function(c) { return c.dataValues });
226                 resolve(map);
227             }
228         });
229     });
230 }
231
232 /**
233  * existFile
234  * 同一ディレクトリに同名のファイルが存在することを確かめる
235  * @param {string} fileName
236  * @param {string} parentDirectory parentDirectoryの絶対パス
237  * @returns {promise} ファイルが存在すればresolve、存在しなければreject
238  */
239 function existFile(fileName, parentDirectory) {
240     return new Promise(function(resolve, reject) {
241         existDirectory(parentDirectory)
242         .catch(function(error) {
243             reject(error);
244         })
245         .then(function(fileId) {
246             var q = {
247                 where: {
248                     name: fileName,
249                     parentId: fileId
250                 }
251             };
252             return Files.findOne(q)
253         })
254         .then(function(r) {
255             if(r === null) {
256                 reject(new Error("\"" + fileName + "\" does not exist in " + '"' + parentDirectory + "\" directory."));
257             } else {
258                 resolve(r.fileId);
259             }
260         });
261     });
262 }
263
264
265 /**
266  * notExistFile
267  * 同一ディレクトリに同名のファイルが存在していないことを確かめる
268  * @param {string}fileName
269  * @param {string}parentDirectory
270  * @returns {promise} ファイルが存在しなければresolve、存在すればreject
271  */
272 function notExistFile(fileName, parentDirectory) {
273     return new Promise(function(resolve, reject) {
274         existDirectory(parentDirectory)
275         .catch(function(error) {
276             reject(error);
277         })
278         .then(function(fileId) {
279             var q = {
280                 where: {
281                     name: fileName,
282                     parentId: fileId
283                 }
284             };
285             return Files.findOne(q)
286         })
287         .then(function(r) {
288             if(r === null) {
289                 resolve();
290             } else {
291                 reject(new Error("\"" + fileName + "\" has already existed in " + '"' + parentDirectory + "\" directory."));
292             }
293         });
294     });
295 }
296
297 /**
298  * existDirectory
299  * ディレクトリが存在することを確認する
300  * @param {string} directory
301  * @returns {promise} ディレクトリが存在すればresolve{fileId)、存在しなければreject
302  */
303 function existDirectory(directory) {
304     return new Promise(function(resolve, reject) {
305         if(!directory) {
306             reject(new Error('parameter "directory" is undefined'));
307         }
308
309         var arrayDirectory; 
310         var root = directory.substr(0,1);
311
312         if(root !== '/') {
313             reject(new Error('directory name should start "/" so that it is absolute path including root.'));
314         }
315
316         if(directory === '/') {
317             resolve('1f83f620-c1ed-11e5-9657-7942989daa00'); // rootのuuid
318         } else {
319             arrayDirectory = directory.split('/');
320             arrayDirectory.shift(); // root
321             arrayDirectory.unshift('/');
322         }
323
324         var directoriesPromise = arrayDirectory.map(function(name) {
325             return getDirectory(name);
326         });
327
328         Promise.all(directoriesPromise)
329         .then(function(r) {
330             var parentId = r[0][0].fileId;
331             var index;
332             for(var i=1;i<r.length;i++) {
333                 index = r[i].map(function(c) { return c.parentId }).indexOf(parentId);
334                 if(index > -1) {
335                     parentId = r[i][index].fileId;
336                 } else {
337                     reject(new Error('"' + directory + '" directory doesn\'t exist.'));
338                 }
339             }
340             resolve(parentId);
341         })
342         .catch(function(error) {
343             reject(new Error('"' + directory + '" directory doesn\'t exist.'));
344         });
345     });
346 }
347
348 /**
349  * notExistDirectory
350  * ディレクトリが存在しないことを確認する
351  * @param {string} directory
352  * @returns {promise} ディレクトリが存在しなければresolve、存在すればreject
353  */
354 function notExistDirectory(directory) {
355     return new Promise(function(resolve, reject) {
356         if(!directory) {
357             resolve();
358         } 
359
360         var arrayDirectory; 
361         var root = directory.substr(0,1);
362
363         if(root !== '/') {
364             resolve();
365         }
366
367         if(directory === '/') {
368             reject(new Error('"' + directory + '" directory exists.'));
369         } else {
370             arrayDirectory = directory.split('/');
371             arrayDirectory.shift(); // root
372             arrayDirectory.unshift('/');
373         }
374
375         var directoriesPromise = arrayDirectory.map(function(name) {
376             return getDirectory(name);
377         });
378         Promise.all(directoriesPromise)
379         .then(function(r) {
380             var parentId = r[0][0].fileId;
381             var index;
382             for(var i=1;i<r.length;i++) {
383                 index = r[i].map(function(c) { return c.parentId }).indexOf(parentId);
384                 if(index > -1) {
385                     parentId = r[i][index].fileId;
386                 } else {
387                     resolve();
388                 }
389             }
390             reject(new Error('"' + directory + '" directory exists.'));
391         })
392         .catch(function(error) {
393             resolve();
394         });
395     });
396 }
397
398 /**
399  * createFile
400  *
401  * @param fileName 
402  * @param parentDirectory
403  * @returns {promise}<sequelize.createの結果を格納したobject | Error>
404  */
405 function createFile(fileName,parentDirectory) {
406     return new Promise(function(resolve, reject) {
407         if(!fileName) {
408             reject(new Error('filename is required.'));
409         }
410         Promise.all([existDirectory(parentDirectory), notExistFile(fileName, parentDirectory) ])
411         .catch(function(error) {
412             reject(error);
413         })
414         .then(function(r) {
415             var parentId = r[0]
416             var q = {
417                 fileId: uuid.v1(),
418                 name: fileName,
419                 parentId: parentId,
420                 fileType: 1 
421             }
422             return Files.create(q)
423         })
424         .then(function(r) {
425             resolve(r.dataValues.fileId);
426         });
427     });
428 }
429
430
431 /**
432  * removeFile
433  * ファイルを削除する
434  * @param {string} fileName
435  * @param {string} parentDirectory
436  * @returns {promise} ファイル削除に成功すればresolve、失敗すればreject
437  */
438 function removeFile(fileName, parentDirectory) {
439     return new Promise(function(resolve, reject) {
440         existFile(fileName, parentDirectory)
441         .catch(function(error) {
442             reject(error);
443         })
444         .then(function(fileId) {
445             var q = {
446                 where: {
447                     fileId: fileId
448                 }
449             };
450             return Files.destroy(q);
451         })
452         .then(function() {
453             resolve();
454         });
455     });
456 }
457
458 /**
459  * createDirectory
460  * ディレクトリを作成
461  * @param directory
462  * @returns {promise} ディレクトリの作成に成功すればresolve、失敗すればreject
463  */
464 function createDirectory(directory) {
465     return new Promise(function(resolve, reject) {
466         if(!directory) {
467             reject(new Error('directory name should start "/" so that it is absolute path including root.'));
468         }
469
470         var leaf = directory.split('/').pop();
471         var parentDirectory = directory.replace('/'+leaf, '');
472         if(!parentDirectory) {
473             parentDirectory = '/';
474         }
475         Promise.all([existDirectory(parentDirectory), notExistDirectory(directory), notExistFile(leaf, parentDirectory)])
476         .catch(function(error) {
477             reject(error);
478         })
479         .then(function(r) {
480             var parentId = r[0];
481             var q = {
482                 fileId: uuid.v1(),
483                 name: leaf,
484                 parentId: parentId,
485                 fileType: 0 
486             }
487             return Files.create(q)
488         })
489         .then(function(r) {
490             resolve(r.dataValues.fileId);
491         });
492     });
493 }
494
495
496 /**
497  * removeDirectory
498  * ディレクトリを削除
499  * @param directory
500  * @returns {promise} ディレクトリの削除に成功すればresolve、失敗すればreject
501  */
502 function removeDirectory(directory) {
503     return new Promise(function(resolve, reject) {
504         var leaf = directory.split('/').pop();
505         var parentDirectory = directory.replace('/'+leaf, '');
506         if(!parentDirectory) {
507             parentDirectory = '/';
508         }
509         Promise.all([existDirectory(parentDirectory), notExistDirectory(directory), notExistFile(leaf, parentDirectory)])
510         .catch(function(error) {
511             reject(error);
512         })
513         .then(function(r) {
514             var parentId = r[0];
515             var q = {
516                 fileId: uuid.v1(),
517                 name: leaf,
518                 parentId: parentId,
519                 fileType: 0 
520             }
521             return Files.create(q)
522         })
523         .then(function(r) {
524             resolve(r.dataValues.fileId);
525         });
526     });
527 }
528
529 /**
530  * test1
531  * test用にデータベースのレコードを追加する関数
532  * @returns {promise}
533  */
534 function test1() {
535     var q = {
536         fileId: uuid.v1(),
537         name: 'hoge.txt',
538         parentId: '1f83f620-c1ed-11e5-9657-7942989daa00', // rootのuuid
539         fileType: 1 
540     };
541     return Files.create(q);
542 }
543
544 /**
545  * test2
546  * test用にデータベースのレコードを追加する関数
547  * @returns {promise}
548  */
549
550 function test2() {
551     var q1 = {
552         fileId: uuid.v1(),
553         name: 'one',
554         parentId: '1f83f620-c1ed-11e5-9657-7942989daa00', // rootのuuid
555         fileType: 0 //directory
556     };
557     return Files.create(q1)
558     .then(function() {
559         var q2 = {
560             fileId: uuid.v1(),
561             name: 'two',
562             parentId: q1.fileId,
563             fileType: 0 
564
565         };
566         return Files.create(q2);
567     })
568     .then(function(r) {
569         var q3 = {
570             fileId: uuid.v1(),
571             name: 'two',
572             parentId: '1f83f620-c1ed-11e5-9657-7942989daa00', //rootのuuid
573             fileType: 0 
574         };
575         return Files.create(q3);
576     })
577     .then(function() {
578         var q4 = {
579             fileId: uuid.v1(),
580             name: 'hogehoge.txt',
581             parentId: q1.fileId,
582             fileType: 1
583         };
584         return Files.create(q4);
585     });
586 }
587
588 function testRest() {
589     var q = {
590         fileId: 'dca94750-c44f-11e5-88c4-f31cdfe97f4f',
591         name: 'debugRest.mrc',
592         parentId: '1f83f620-c1ed-11e5-9657-7942989daa00', //rootのuuid
593         fileType: 1 // file
594     };
595     return Files.create(q);
596 }
597
598 module.exports = { instance: instance };