fixing up file store (needs refactoring and cleanup)...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-09-03 13:37:49 +03:00
parent d1fdb7a6ca
commit 4846a5d69d
4 changed files with 61 additions and 17 deletions

View File

@ -187,11 +187,16 @@ object.Constructor('BasePage', {
return pwpath.dirname(this.path) }, return pwpath.dirname(this.path) },
//set dir(value){ }, //set dir(value){ },
get title(){ return async function(){ /*/ XXX TITLE...
return (await this.data).title // NOTE: .__title is intentionally not persistent...
?? this.path }.call(this) }, __title: undefined,
get title(){
return this.__title
?? this.path },
set title(value){ set title(value){
this.__title = value
this.__update__({title: value}) }, this.__update__({title: value}) },
//*/
get isPattern(){ get isPattern(){
return this.path.includes('*') }, return this.path.includes('*') },
@ -265,6 +270,11 @@ object.Constructor('BasePage', {
// single page... // single page...
// XXX ENERGETIC... // XXX ENERGETIC...
var res = await this.store.get(this.path, !!this.strict, !!await this.energetic) var res = await this.store.get(this.path, !!this.strict, !!await this.energetic)
/*/ XXX TITLE...
// load the title if set...
res.title
?? (this.__title = res.title)
//*/
return typeof(res) == 'function' ? return typeof(res) == 'function' ?
res.bind(this) res.bind(this)
: res }).call(this) }, : res }).call(this) },

View File

@ -9,6 +9,7 @@
var fs = require('fs') var fs = require('fs')
var glob = require('glob') var glob = require('glob')
var cp = require('child_process')
var object = require('ig-object') var object = require('ig-object')
var types = require('ig-types') var types = require('ig-types')
@ -18,6 +19,8 @@ var pwpath = require('../path')
var base = require('./base') var base = require('./base')
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// //
@ -97,7 +100,8 @@ async function(base, sub, options){
var mkdir = var mkdir =
module.mkdir = module.mkdir =
async function(base, sub, options){ async function(base, sub, options){
if(typeof(sub) != 'string'){ if(typeof(sub) != 'string'
&& !(sub instanceof Array)){
options = sub ?? options options = sub ?? options
sub = base sub = base
base = null } base = null }
@ -146,7 +150,7 @@ async function(base, sub, data, options){
target = pwpath.join(target, index) } target = pwpath.join(target, index) }
// create path / parts of path... // create path / parts of path...
} else { } else {
var levels = pwpath.split(target) var levels = pwpath.split(sub)
levels.pop() levels.pop()
// ensure the parent dir exists... // ensure the parent dir exists...
await module.mkdir( await module.mkdir(
@ -524,10 +528,16 @@ module.FileStoreRO = {
// XXX // XXX
__path__: 'data/fs', __path__: 'data/fs',
__pwiki_path__: '/.pwiki/',
__metadata_path__: '$PWIKI/metadata',
// XXX should this be "index" or ".index"??? // XXX should this be "index" or ".index"???
__directory_text__: '.index', __directory_text__: '.index',
expandPWikiPath: function(...path){
return pwpath.join(...path)
.replace(/\$PWIKI/, this.__pwiki_path__) },
// XXX do we remove the extension??? // XXX do we remove the extension???
// XXX cache??? // XXX cache???
__paths__: async function(){ __paths__: async function(){
@ -548,12 +558,14 @@ module.FileStoreRO = {
&& path }, && path },
__get__: async function(path){ __get__: async function(path){
var p = pwpath.join(this.__path__, path) var p = pwpath.join(this.__path__, path)
var m = this.expandPWikiPath(this.__path__, this.__metadata_path__, path)
var {atimeMs, mtimeMs, ctimeMs, birthtimeMs} = await fs.promises.stat(p) var {atimeMs, mtimeMs, ctimeMs, birthtimeMs} = await fs.promises.stat(p)
return { return {
atime: atimeMs, atime: atimeMs,
mtime: mtimeMs, mtime: mtimeMs,
ctime: ctimeMs, ctime: ctimeMs,
text: await module.read(p, {index: this.__directory_text__}) text: await module.read(p, {index: this.__directory_text__}),
...JSON.parse(await module.read(m, {index: this.__directory_text__}) || '{}'),
} }, } },
__update__: function(){}, __update__: function(){},
@ -569,12 +581,14 @@ module.FileStore = {
// XXX // XXX
__path__: 'data/fs', __path__: 'data/fs',
__backup_path__: '/.pwiki/backup', __pwiki_path__: '/.pwiki',
__lock_path__: '/.pwiki/lock', __backup_path__: '$PWIKI/backup',
__lock_path__: '$PWIKI/lock',
// XXX should this be "index" or ".index"???
__directory_text__: '.index', __directory_text__: '.index',
// prevent more than one handler to write to a store...
//
__clear_lock__: [ __clear_lock__: [
`SIGINT`, `SIGINT`,
`SIGUSR1`, `SIGUSR1`,
@ -586,17 +600,20 @@ module.FileStore = {
//`uncaughtException`, //`uncaughtException`,
], ],
__exit_lock_handler: undefined, __exit_lock_handler: undefined,
// prevent more than one handler to write to a store...
ensureLock: async function(){ ensureLock: async function(){
var that = this var that = this
var lock = this.__path__ + this.__lock_path__ var lock = this.expandPWikiPath(this.__path__, this.__lock_path__)
// check lock... // check lock...
if(fs.existsSync(lock)){ if(fs.existsSync(lock)){
if(await module.read(lock) != process.pid){ if(await module.read(lock) != process.pid){
throw new Error('attempting to write to a locked store:', this.__path__) } throw new Error('attempting to write to a locked store:', this.__path__) }
// set lock... // set lock...
} else { } else {
module.update(lock, `${process.pid}`) await module.update(lock, `${process.pid}`)
// keep the pwiki dir hidden on windows...
if(process.platform == 'win32'){
cp.execSync('attrib +h '+
this.expandPWikiPath(this.__path__, this.__pwiki_path__)) }
this.__exit_lock_handler = this.__exit_lock_handler =
this.__exit_lock_handler this.__exit_lock_handler
// NOTE: this must be sync as deferred calls might // NOTE: this must be sync as deferred calls might
@ -611,12 +628,25 @@ module.FileStore = {
// XXX do we write all the data or only the .text??? // XXX do we write all the data or only the .text???
__update__: async function(path, data, mode='update'){ __update__: async function(path, data, mode='update'){
this.ensureLock() this.ensureLock()
// metadata...
module.update(
this.__path__,
this.expandPWikiPath(this.__metadata_path__, path),
JSON.stringify(data),
{index: this.__directory_text__})
// text...
return module.update( return module.update(
this.__path__, path, this.__path__, path,
data.text, data.text,
{index: this.__directory_text__}) }, {index: this.__directory_text__}) },
__delete__: async function(path){ __delete__: async function(path){
this.ensureLock() this.ensureLock()
// metadata...
module.clear(
this.__path__,
this.expandPWikiPath(this.__metadata_path__, path),
{index: this.__directory_text__})
// text...
return module.clear( return module.clear(
this.__path__, path, this.__path__, path,
{index: this.__directory_text__}) }, {index: this.__directory_text__}) },
@ -634,7 +664,7 @@ module.FileStore = {
this.__path__, path, this.__path__, path,
{ {
index: this.__directory_text__, index: this.__directory_text__,
backup: this.__backup_path__, backup: this.expandPWikiPath(this.__backup_path__),
...options, ...options,
}) }, }) },
restore: async function(path='**', options={}){ restore: async function(path='**', options={}){
@ -643,7 +673,7 @@ module.FileStore = {
this.__path__, path, this.__path__, path,
{ {
index: this.__directory_text__, index: this.__directory_text__,
backup: this.__backup_path__, backup: this.expandPWikiPath(this.__backup_path__),
...options, ...options,
}) }, }) },
} }

View File

@ -173,12 +173,15 @@ require(['./browser'], function(browser){
pwiki pwiki
.onBeforeNavigate(function(){ .onBeforeNavigate(function(){
saveNow() }) saveNow() })
.onNavigate(function(){ .onNavigate(async function(){
// NOTE: we do not need to directly update location.hash here as // NOTE: we do not need to directly update location.hash here as
// that will push an extra history item... // that will push an extra history item...
history.replaceState( history.replaceState(
{path: this.location}, {path: this.location},
this.title, // XXX TITLE .title must be sync as history will not wait for
// the value even it await is given...
//this.title,
this.path,
'#'+this.location '#'+this.location
+(this.hash ? +(this.hash ?
'#'+this.hash '#'+this.hash

View File

@ -24,8 +24,9 @@
* - count + block-offset (preferred) * - count + block-offset (preferred)
* - count + elem-offset * - count + elem-offset
* - from + to * - from + to
* XXX TITLE revise how title is handled...
* ...do we need a separate title and path???
* XXX revise/update sort... * XXX revise/update sort...
* XXX fs store: metadata and cache...
* XXX prevent paths from using reserved chars like: ":", "#", ... * XXX prevent paths from using reserved chars like: ":", "#", ...
* XXX ASAP: MetaStore: need to correctly integrate the following store * XXX ASAP: MetaStore: need to correctly integrate the following store
* methods: * methods: