Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xiaowu Zhang
jio
Commits
90d37ed6
Commit
90d37ed6
authored
Dec 20, 2012
by
Sven Franck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PUTATTACHEMENT working, removed methods to util
parent
eca94a2a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
471 additions
and
337 deletions
+471
-337
src/jio.storage/intro.js
src/jio.storage/intro.js
+82
-48
src/jio.storage/localstorage.js
src/jio.storage/localstorage.js
+266
-260
src/jio/commands/command.js
src/jio/commands/command.js
+2
-0
test/jiotests.js
test/jiotests.js
+121
-29
No files found.
src/jio.storage/intro.js
View file @
90d37ed6
...
...
@@ -19,14 +19,14 @@ var utilities = {
isObjectEmpty
:
function
(
obj
)
{
var
key
;
if
(
obj
.
length
&&
obj
.
length
>
0
){
if
(
obj
.
length
&&
obj
.
length
>
0
)
{
return
false
;
}
if
(
obj
.
length
&&
obj
.
length
===
0
){
if
(
obj
.
length
&&
obj
.
length
===
0
)
{
return
true
;
}
for
(
key
in
obj
)
{
if
({}.
hasOwnProperty
.
call
(
obj
,
key
)){
if
({}.
hasOwnProperty
.
call
(
obj
,
key
))
{
return
false
;
}
}
...
...
@@ -41,7 +41,7 @@ var utilities = {
isObjectSize
:
function
(
obj
)
{
var
size
=
0
,
key
;
for
(
key
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
key
)){
if
(
obj
.
hasOwnProperty
(
key
))
{
size
++
;
}
}
...
...
@@ -54,11 +54,11 @@ var utilities = {
* @param {haystack} array - active leaves (versions of a document)
* @returns {boolean} string- true/false
*/
isInObject
:
function
(
needle
,
haystack
){
isInObject
:
function
(
needle
,
haystack
)
{
var
length
=
haystack
.
length
;
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
if
(
haystack
[
i
]
===
needle
){
if
(
haystack
[
i
]
===
needle
)
{
return
true
;
}
}
...
...
@@ -70,7 +70,7 @@ var utilities = {
* @param {needle} string - docId
* @returns {boolean} string- true/false
*/
isUUID
:
function
(
documentId
){
isUUID
:
function
(
documentId
)
{
var
reg
=
/^
[
0-9a-f
]{8}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{12}
$/i
.
test
(
documentId
);
return
reg
;
},
...
...
@@ -81,10 +81,10 @@ var utilities = {
* @param {reason} string - the error reason
* @returns {e} object - error object
*/
throwError
:
function
(
code
,
reason
)
{
throwError
:
function
(
code
,
reason
)
{
var
statusText
,
error
,
message
,
errorObject
;
switch
(
code
)
{
switch
(
code
)
{
case
409
:
statusText
=
'
Conflict
'
;
...
...
@@ -195,7 +195,7 @@ var utilities = {
* @stored - 'jio/local/USR/APP/FILE_NAME'
* @returns {doc} object - document object
*/
createDocument
:
function
(
docId
,
docPath
){
createDocument
:
function
(
docId
,
docPath
)
{
var
now
=
Date
.
now
(),
doc
=
{},
hash
=
utilities
.
hashCode
(
''
+
doc
+
'
'
+
now
+
''
);
...
...
@@ -221,13 +221,31 @@ var utilities = {
* @param {docid} string - id for the new document
* @param {docpath} string - the path where to store the document
* @param {previousRevision} string - the previous revision
* @param {attachmentId} - string - in case attachments are handled
* @returns {doc} object - new document
*/
updateDocument
:
function
(
doc
,
docPath
,
previousRevision
)
{
updateDocument
:
function
(
doc
,
docPath
,
previousRevision
,
attachmentId
)
{
var
now
=
Date
.
now
(),
rev
=
utilities
.
generateNextRevision
(
previousRevision
,
''
+
doc
+
'
'
+
now
+
''
);
// in case the update is made because of an attachment
if
(
attachmentId
!==
undefined
)
{
// create _attachments
if
(
doc
.
_attachments
===
undefined
){
doc
.
_attachments
=
{};
}
// create _attachments object for this attachment
if
(
doc
.
_attachments
[
attachmentId
]
===
undefined
){
doc
.
_attachments
[
attachmentId
]
=
{};
}
// set revpos
doc
.
_attachments
[
attachmentId
].
revpos
=
parseInt
(
doc
.
_rev
.
split
(
'
-
'
)[
0
],
10
);
}
// update document
doc
.
_rev
=
rev
.
join
(
'
-
'
);
doc
.
_revisions
.
ids
.
unshift
(
rev
[
1
]);
...
...
@@ -237,7 +255,6 @@ var utilities = {
"
rev
"
:
rev
.
join
(
'
-
'
),
"
status
"
:
"
available
"
});
return
doc
;
},
...
...
@@ -255,14 +272,13 @@ var utilities = {
* @info - deleted versions/branches = "status deleted"
* @info - no active leaves will delete tree, too
*/
createDocumentTree
:
function
(
doc
)
{
createDocumentTree
:
function
(
doc
)
{
var
tree
=
{
type
:
'
leaf
'
,
status
:
'
available
'
,
rev
:
doc
.
_rev
,
kids
:[]
};
return
tree
;
},
...
...
@@ -273,50 +289,57 @@ var utilities = {
* @param {new_rev } string - revison of the tree node to add as leaf
* @param {revs_info} object- history of new_rev to merge with remote tree
*/
updateDocumentTree
:
function
(
docTreeNode
,
old_rev
,
new_rev
,
revs_info
){
if
(
typeof
revs_info
===
"
object
"
){
updateDocumentTree
:
function
(
docTreeNode
,
old_rev
,
new_rev
,
revs_info
,
deletedLeaf
)
{
if
(
typeof
revs_info
===
"
object
"
)
{
// a new document version is being stored from another storage
utilities
.
mergeRemoteTree
(
docTreeNode
,
docTreeNode
,
old_rev
,
new_rev
,
revs_info
,
[],
false
);
utilities
.
mergeRemoteTree
(
docTreeNode
,
docTreeNode
,
old_rev
,
new_rev
,
revs_info
,
[],
false
,
deletedLeaf
);
}
else
{
// update an existing version of document = add a node to the tree
utilities
.
setTreeNode
(
docTreeNode
,
old_rev
,
new_rev
);
utilities
.
setTreeNode
(
docTreeNode
,
old_rev
,
new_rev
,
'
available
'
);
}
return
docTreeNode
;
},
// ==================== SET/MERGE/CHECK TREE NODES ==================
/**
* @method setTreeNode
- adds a new tree node/changes leaf to branch
* @method setTreeNode - adds a new tree node/changes leaf to branch
* @param {docTreeNode} object - document tree
* @param {old_rev} string - revision of the tree node to set to "branch"
* @param {new_rev } string - revison of the tree node to add as leaf
* @param {old_rev} string - revision of the tree node to set to "branch"
* @param {new_rev } string - revison of the tree node to add as leaf
* @param {new_status}string- status the new node should have
* @info - status is necessary, because we may also
* add deleted nodes to the tree from a
* remote storage
*/
setTreeNode
:
function
(
docTreeNode
,
old_rev
,
new_rev
){
setTreeNode
:
function
(
docTreeNode
,
old_rev
,
new_rev
,
new_status
){
var
kids
=
docTreeNode
[
'
kids
'
],
rev
=
docTreeNode
[
'
rev
'
],
numberOfKids
,
i
,
key
;
for
(
key
in
docTreeNode
){
if
(
key
===
"
rev
"
){
for
(
key
in
docTreeNode
){
if
(
key
===
"
rev
"
){
// grow the tree
if
(
old_rev
===
rev
&&
new_rev
!==
rev
)
{
if
(
old_rev
===
rev
&&
new_rev
!==
rev
)
{
docTreeNode
.
type
=
'
branch
'
;
docTreeNode
.
status
=
'
deleted
'
;
docTreeNode
.
kids
.
push
({
type
:
'
leaf
'
,
status
:
'
available
'
,
status
:
new_status
,
rev
:
new_rev
,
kids
:[]
});
}
else
{
// traverse until correct node is found!
if
(
utilities
.
isObjectEmpty
(
kids
)
===
false
){
if
(
utilities
.
isObjectEmpty
(
kids
)
===
false
)
{
numberOfKids
=
utilities
.
isObjectSize
(
kids
);
for
(
i
=
0
;
i
<
numberOfKids
;
i
+=
1
){
utilities
.
setTreeNode
(
kids
[
i
],
old_rev
,
new_rev
);
utilities
.
setTreeNode
(
kids
[
i
],
old_rev
,
new_rev
,
new_status
);
}
}
}
...
...
@@ -337,30 +360,29 @@ var utilities = {
* for the new tree node (we are copy&pasting
* from another storage)
*/
mergeRemoteTree
:
function
(
initialTree
,
docTreeNode
,
old_rev
,
new_rev
,
newDocumentRevisions
,
addNodes
,
onTree
){
mergeRemoteTree
:
function
(
initialTree
,
docTreeNode
,
old_rev
,
new_rev
,
newDocumentRevisions
,
addNodes
,
onTree
,
deletedLeaf
){
var
sync_rev
=
newDocumentRevisions
[
0
].
rev
,
current_tree_rev
=
docTreeNode
[
'
rev
'
],
kids
=
docTreeNode
[
'
kids
'
],
nodeStatus
=
'
available
'
,
addNodesLen
,
numberOfKids
,
key
,
i
,
j
;
for
(
key
in
docTreeNode
)
{
if
(
key
===
"
rev
"
)
{
for
(
key
in
docTreeNode
)
{
if
(
key
===
"
rev
"
)
{
// comm
e
on ancestor? = does the revision on the current
// common ancestor? = does the revision on the current
// tree node match the currently checked remote tree
// revision
// match = common ancestor
if
(
sync_rev
===
current_tree_rev
){
if
(
sync_rev
===
current_tree_rev
){
onTree
=
true
;
// in order to loop we also add the revision of
// the common ancestor node to the array
// using push!
...
...
@@ -370,19 +392,20 @@ var utilities = {
// the addNodes array will now look like this
// [current_node, all_missing_nodes]
for
(
j
=
0
;
j
<
addNodesLen
;
j
+=
1
){
utilities
.
setTreeNode
(
initialTree
,
addNodes
[
j
],
addNodes
[
j
+
1
]
);
for
(
j
=
0
;
j
<
addNodesLen
;
j
+=
1
){
// last node being added is deleted
if
(
deletedLeaf
===
true
&&
j
===
addNodesLen
-
1
){
nodeStatus
=
'
deleted
'
;
}
utilities
.
setTreeNode
(
initialTree
,
addNodes
[
j
],
addNodes
[
j
+
1
],
nodeStatus
);
}
// no match = continue down the tree
}
else
if
(
utilities
.
isObjectEmpty
(
kids
)
===
false
){
numberOfKids
=
utilities
.
isObjectSize
(
kids
);
for
(
i
=
0
;
i
<
numberOfKids
;
i
+=
1
){
utilities
.
mergeRemoteTree
(
initialTree
,
kids
[
i
],
old_rev
,
new_rev
,
newDocumentRevisions
,
addNodes
,
onTree
);
newDocumentRevisions
,
addNodes
,
onTree
,
deletedLeaf
);
}
// end of tree = start over checking the next remote revision
...
...
@@ -403,13 +426,22 @@ var utilities = {
// this should start over with the full document tree
// otherwise it will only continue on the current (last) node
utilities
.
mergeRemoteTree
(
initialTree
,
initialTree
,
old_rev
,
new_rev
,
newDocumentRevisions
,
addNodes
,
onTree
);
newDocumentRevisions
,
addNodes
,
onTree
,
deletedLeaf
);
}
}
}
return
docTreeNode
;
},
getActiveLeaves
:
function
(
docTreeNode
)
{
var
activeLeaves
=
utilities
.
getLeavesOnTree
(
docTreeNode
);
activeLeaves
=
typeof
activeLeaves
===
"
string
"
?
[
activeLeaves
]
:
activeLeaves
;
return
activeLeaves
;
},
/**
* @method getLeavesOnTree - finds all leaves on a tree
* @param {docTree} string - the tree for this document
...
...
@@ -461,7 +493,10 @@ var utilities = {
status
=
docTreeNode
[
'
status
'
],
kids
=
docTreeNode
[
'
kids
'
],
rev
=
docTreeNode
[
'
rev
'
],
result
=
false
,
numberOfKids
,
i
,
key
;
result
=
false
,
numberOfKids
,
i
,
key
;
for
(
key
in
docTreeNode
){
if
(
key
===
"
rev
"
){
...
...
@@ -470,8 +505,7 @@ var utilities = {
(
type
===
'
branch
'
||
status
===
'
deleted
'
)
){
result
=
true
;
}
if
(
typeof
kids
===
"
object
"
&&
utilities
.
isObjectEmpty
(
kids
)
===
false
){
if
(
utilities
.
isObjectEmpty
(
kids
)
===
false
){
numberOfKids
=
utilities
.
isObjectSize
(
kids
);
for
(
i
=
0
;
i
<
numberOfKids
;
i
+=
1
){
...
...
src/jio.storage/localstorage.js
View file @
90d37ed6
...
...
@@ -165,9 +165,102 @@ var newLocalStorage = function ( spec, my ) {
};
/**
* @method post
*
* Create a document in local storage.
* runDocumentUpdate - run the whole update process for localstorage
* @param {object} doc - the original document object.
* @param {object} docTree - the document tree
* @param {object} command - command object
* @param {string} docId - document id
* @param {string} attachmentId - attachmentId
* @param {string} docPath - document paths
* @param {string} prev_rev- previous revision
* @param {string} treePath- document tree paths
* @param {boolean} sync - whether this is an update or sync operation!
* @returns {object} success- success object
*/
priv
.
runDocumentUpdate
=
function
(
doc
,
docTree
,
command
,
docId
,
attachmentId
,
docPath
,
prev_rev
,
treePath
,
sync
){
var
docPathRev
,
newRevision
,
revs_info
,
deletedLeaf
;
// update ...I don't know what this is doing?
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
// update document - not when put sync-ing
if
(
sync
===
false
){
// create a new revision
doc
=
utilities
.
updateDocument
(
doc
,
docPath
,
prev_rev
,
attachmentId
);
docPathRev
=
docPath
+
'
/
'
+
doc
.
_rev
;
newRevision
=
doc
.
_rev
;
revs_info
=
undefined
;
// delete old doc (.../DOCID/old_REVISION)
localstorage
.
deleteItem
(
docPath
+
'
/
'
+
prev_rev
);
}
else
{
docPathRev
=
docPath
+
'
/
'
+
doc
.
_revs_info
[
0
].
rev
;
newRevision
=
null
;
revs_info
=
doc
.
_revs_info
;
if
(
revs_info
[
0
].
status
===
'
deleted
'
){
deletedLeaf
=
true
;
}
}
if
(
deletedLeaf
===
undefined
){
// store new doc (.../DOCID/new_REVISION)
localstorage
.
setItem
(
docPathRev
,
doc
);
}
// update tree and store
localstorage
.
setItem
(
treePath
,
utilities
.
updateDocumentTree
(
docTree
,
prev_rev
,
newRevision
,
revs_info
,
deletedLeaf
)
);
// return SUCCESS
return
priv
.
manageOptions
({
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
);
};
/**
* runDocumentCreate - run the whole create process for localstorage
* @param {string} docId - document id
* @param {object} command - command object
* @returns {object} success- success object
*/
priv
.
runDocumenCreate
=
function
(
docId
,
command
){
// create new document and tree
var
docPath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docId
,
doc
=
utilities
.
createDocument
(
docId
,
docPath
),
tree
=
utilities
.
createDocumentTree
(
doc
),
treePath
=
docPath
+
'
/revision_tree
'
;
// store document
localstorage
.
setItem
(
docPath
+
'
/
'
+
doc
.
_rev
,
doc
);
// store tree
localstorage
.
setItem
(
treePath
,
tree
);
// add user
if
(
!
priv
.
doesUserExist
(
priv
.
secured_username
))
{
priv
.
addUser
(
priv
.
secured_username
);
}
// add fileName
priv
.
addFileName
(
docId
);
// return SUCCESS
return
priv
.
manageOptions
({
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
);
};
// =============================== METHODS ======================
/**
* @method post - Create a document in local storage.
* @stored - 'jio/local/USR/APP/FILE_NAME/REVISION'.
*
* Available options:
* - {boolean} conflicts - Add a conflicts object to the response
...
...
@@ -178,17 +271,10 @@ var newLocalStorage = function ( spec, my ) {
that
.
post
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
docId
=
command
.
getDocId
(),
docPath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docId
,
tree
,
treePath
=
docPath
+
'
/revision_tree
'
,
docTree
=
localstorage
.
getItem
(
treePath
),
var
docId
=
command
.
getDocId
(),
reg
=
utilities
.
isUUID
(
docId
);
// no attachments allowed
//
403 -
no attachments allowed
if
(
command
.
getAttachmentId
())
{
that
.
error
(
utilities
.
throwError
(
403
,
'
Attachment cannot be added with a POST request
'
)
...
...
@@ -196,50 +282,25 @@ var newLocalStorage = function ( spec, my ) {
return
;
}
if
(
reg
!==
true
)
{
// id was supplied, use PUT
// 403 id was supplied, use PUT
if
(
reg
!==
true
)
{
that
.
error
(
utilities
.
throwError
(
403
,
'
ID cannot be supplied with a POST request. Please use PUT
'
)
);
return
;
// ok
}
else
{
// create new document
doc
=
utilities
.
createDocument
(
docId
,
docPath
);
// store
localstorage
.
setItem
(
docPath
+
'
/
'
+
doc
.
_rev
,
doc
);
// create and store new document.tree
tree
=
utilities
.
createDocumentTree
(
doc
);
// store
localstorage
.
setItem
(
treePath
,
tree
);
// add user
if
(
!
priv
.
doesUserExist
(
priv
.
secured_username
))
{
priv
.
addUser
(
priv
.
secured_username
);
}
// add fileName
priv
.
addFileName
(
docId
);
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
)
that
.
success
(
priv
.
runDocumenCreate
(
docId
,
command
)
);
}
});
};
// end post
};
/**
* @method put
*
* Create or Update a document in local storage.
* @method put - Create or Update a document in local storage.
* @stored - 'jio/local/USR/APP/FILE_NAME/REVISION'.
*
* Available options:
* - {boolean} conflicts - Add a conflicts object to the response
...
...
@@ -254,14 +315,17 @@ var newLocalStorage = function ( spec, my ) {
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
),
docPath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docId
,
treePath
=
docPath
+
'
/revision_tree
'
,
tree
,
treePath
=
docPath
+
'
/revision_tree
'
,
docTree
=
localstorage
.
getItem
(
treePath
),
doc
,
docPathRev
,
activeLeaves
,
reg
=
utilities
.
isUUID
(
docId
),
newDocTree
;
doc
,
docPathRev
,
activeLeaves
,
reg
=
utilities
.
isUUID
(
docId
);
// no tree = create document or error
if
(
!
docTree
)
{
//
id/revision provided = update, revision must be incorrect
//
404 id/revision provided = update, incorrect revision
if
(
prev_rev
!==
undefined
&&
reg
===
false
){
that
.
error
(
utilities
.
throwError
(
404
,
'
Document not found, please check revision and/or ID
'
)
...
...
@@ -269,7 +333,7 @@ var newLocalStorage = function ( spec, my ) {
return
;
}
// no revision and UUID = create, no id provided
//
409
no revision and UUID = create, no id provided
if
(
prev_rev
===
undefined
&&
reg
===
true
){
that
.
error
(
utilities
.
throwError
(
409
,
'
Missing Document ID and or Revision
'
)
...
...
@@ -278,238 +342,179 @@ var newLocalStorage = function ( spec, my ) {
}
// if passed here, we create.
// it could be create (id+content) or update (without revision)
// but since no tree was found and the tree includes id only
// we only end here with a NEW id, so update sans revision cannot
// be the case.
// it could be create (id+content) or update (sans revision)
// but since no tree was found we end here with a NEW id only
// (otherwise tree would be have been found).
that
.
success
(
priv
.
runDocumenCreate
(
docId
,
command
)
);
// create and store new document
doc
=
utilities
.
createDocument
(
docId
,
docPath
);
}
else
{
// found a tree
activeLeaves
=
utilities
.
getActiveLeaves
(
docTree
);
//
store
localstorage
.
setItem
(
docPath
+
'
/
'
+
doc
.
_rev
,
doc
);
//
check if revision is on doc-tree and if it is an active leaf
if
(
!
utilities
.
isInObject
(
prev_rev
,
activeLeaves
)
)
{
// create and store new document.tree
tree
=
utilities
.
createDocumentTree
(
doc
);
// check if it's a dead leaf (wrong revision)
if
(
utilities
.
isDeadLeaf
(
prev_rev
,
docTree
)
){
// 409 deleted leaf/branch = wrong revision
that
.
error
(
utilities
.
throwError
(
409
,
'
Revision supplied is not the latest revision
'
)
);
return
;
}
// store
localstorage
.
setItem
(
treePath
,
tree
);
// maybe a sync-PUT from another storage, we must
// have revs_info option, otherwise we cannot know
// where to put the file and update the storage tree
if
(
!
utilities
.
isDeadLeaf
(
prev_rev
,
docTree
)
&&
command
.
getDocInfo
(
'
_revs_info
'
)
===
undefined
){
// add user
if
(
!
priv
.
doesUserExist
(
priv
.
secured_username
))
{
priv
.
addUser
(
priv
.
secured_username
);
// 409 no revs_info provided
that
.
error
(
utilities
.
throwError
(
409
,
'
Missing revs_info required for sync-put
'
)
);
return
;
}
else
{
// SYNC PUT
// revs_info is provided, this is a new version
// store this document and merge
// NOTE: we also have to SYNC PUT deleted versions
// otherwise the tree will not be the same AND
// other storages will not know which versions of a
// document have been deleted!!!!
// get the new document
doc
=
command
.
getDoc
();
// ok
that
.
success
(
priv
.
runDocumentUpdate
(
doc
,
docTree
,
command
,
docId
,
undefined
,
docPath
,
prev_rev
,
treePath
,
true
)
);
}
}
else
{
// revision matches a currently active leaf
// = update of an existing document version
// get doc
docPathRev
=
docPath
+
'
/
'
+
prev_rev
;
doc
=
localstorage
.
getItem
(
docPathRev
);
if
(
!
doc
){
// 404 document not available, should not happen!
that
.
error
(
utilities
.
throwError
(
404
,
'
Referenced document not found
'
)
);
return
;
}
else
{
// ok
that
.
success
(
priv
.
runDocumentUpdate
(
doc
,
docTree
,
command
,
docId
,
undefined
,
docPath
,
prev_rev
,
treePath
,
false
)
);
}
}
}
});
};
/**
* @method putAttachment - Saves/updates an attachment of a document
* @stored at - 'jio/local/USR/APP/FILE_NAME/REVISION/ATTACHMENTID'.
*
* Available options:
* - {boolean} conflicts - Add a conflicts object to the response
* - {boolean} revs - Add the revisions history of the document
* - {boolean} revs_info - Add revisions informations
*/
that
.
putAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
docId
=
command
.
getDocId
(),
docPath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docId
,
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
),
treePath
=
docPath
+
'
/revision_tree
'
,
docTree
=
localstorage
.
getItem
(
treePath
),
doc
,
docPathRev
,
activeLeaves
,
attachmentId
,
attachment
,
attachmentPath
;
// add fileName
priv
.
addFileName
(
docId
);
if
(
!
docTree
)
{
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
)
// 404 document wasn't found = wrong id or revision
that
.
error
(
utilities
.
throwError
(
404
,
'
Document not found, please check document ID
'
)
);
return
;
}
else
{
// found a tree
- get active leaves
activeLeaves
=
utilities
.
get
LeavesOnTree
(
docTree
);
// found a tree
activeLeaves
=
utilities
.
get
ActiveLeaves
(
docTree
);
// this should return an array of all active leaves
// or a single leaf, which needs to be put into an array
activeLeaves
=
typeof
activeLeaves
===
"
string
"
?
[
activeLeaves
]
:
activeLeaves
;
// check if revision is on doc-tree and is an active leaf
if
(
!
utilities
.
isInObject
(
prev_rev
,
activeLeaves
)
)
{
// check if it's a branch/dead leaf (deleted/updated version)
if
(
utilities
.
isDeadLeaf
(
prev_rev
,
docTree
)
){
that
.
error
(
utilities
.
throwError
(
409
,
'
Revision supplied is not the latest revision
'
)
);
return
;
}
// check if revision is on tree
if
(
utilities
.
isInObject
(
prev_rev
,
activeLeaves
)
)
{
// maybe a sync-PUT from another storage, we must
// have revs_info option, otherwise we cannot know
// where to put the file and update the storage tree
if
(
!
utilities
.
isDeadLeaf
(
prev_rev
,
docTree
)
&&
command
.
getDocInfo
(
'
_revs_info
'
)
===
undefined
){
that
.
error
(
utilities
.
throwError
(
409
,
'
Missing revs_info required for sync-put
'
)
);
return
;
}
else
{
// SYNC PUT
// revs_info is provided, this is a new version
// store this document and merge
// get the new document
doc
=
command
.
getDoc
();
// we are not updating, this is a copy&paste sync
// therefore the path should have the revision of
// the current document. No new revision hash
// needs to be created
docPathRev
=
docPath
+
'
/
'
+
doc
.
_revs_info
[
0
].
rev
;
// update ...???
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
// store the new item.
localstorage
.
setItem
(
docPathRev
,
doc
);
// update tree and store
localstorage
.
setItem
(
treePath
,
utilities
.
updateDocumentTree
(
docTree
,
prev_rev
,
null
,
doc
.
_revs_info
)
);
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docId
,
rev
:
prev_rev
},
command
,
doc
)
);
}
}
else
{
// check if dead leaf
if
(
utilities
.
isDeadLeaf
(
prev_rev
,
docTree
)
){
// revision matches a currently active leaf
// update of an existing document version
// 409 deleted leaf/branch = wrong revision
that
.
error
(
utilities
.
throwError
(
409
,
'
Trying to update on a previous document version
'
)
);
return
;
// get doc
docPathRev
=
docPath
+
'
/
'
+
prev_rev
;
doc
=
localstorage
.
getItem
(
docPathRev
);
}
else
{
// revision is ok
attachmentId
=
command
.
getAttachmentId
(
);
if
(
!
doc
){
// documen not available, should not happen!
that
.
error
(
utilities
.
throwError
(
40
4
,
'
Referenced document not foun
d
'
)
// 409 missing attachment id
if
(
!
attachmentId
){
that
.
error
(
utilities
.
throwError
(
40
9
,
'
No attachment id specifie
d
'
)
);
return
;
}
else
{
// update ...?
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
// update document
doc
=
utilities
.
updateDocument
(
doc
,
docPath
,
prev_rev
);
// store new doc (.../DOCID/new_REVISION)
localstorage
.
setItem
(
docPath
+
'
/
'
+
doc
.
_rev
,
doc
);
// delete old doc (.../DOCID/old_REVISION)
localstorage
.
deleteItem
(
docPath
+
'
/
'
+
prev_rev
);
// update tree and store
localstorage
.
setItem
(
treePath
,
utilities
.
updateDocumentTree
(
docTree
,
prev_rev
,
doc
.
_rev
,
undefined
)
);
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
)
// set attachment
attachmentPath
=
docPath
+
'
/
'
+
prev_rev
+
'
/
'
+
attachmentId
;
attachment
=
localstorage
.
getItem
(
attachmentPath
);
// store/update attachment
localstorage
.
setItem
(
attachmentPath
,
command
.
getContent
());
// get doc
docPathRev
=
docPath
+
'
/
'
+
prev_rev
;
doc
=
localstorage
.
getItem
(
docPathRev
);
// ok
that
.
success
(
priv
.
runDocumentUpdate
(
doc
,
docTree
,
command
,
docId
,
attachmentId
,
docPath
,
prev_rev
,
treePath
,
false
)
);
}
// found a doc to update
}
// updating existing document
}
// found a tree
});
// set timeout
};
// end put
/**
* Saves/updates an attachment of a specified document.
* attachment will be stored @ 'jio/local/USR/APP/FILE_NAME/ATTACHMENTID'.
* @method putAttachment
*/
that
.
putAttachment
=
function
(
command
)
{
var
now
=
Date
.
now
();
// wait a little in order to simulate asynchronous saving
setTimeout
(
function
()
{
var
docid
,
doc
,
docpath
,
attmtid
,
attmt
,
attmtpath
,
prev_rev
,
rev
;
docid
=
command
.
getDocId
();
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
);
docpath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docid
;
// 404
doc
=
localstorage
.
getItem
(
docpath
);
if
(
!
doc
)
{
that
.
error
({
status
:
404
,
statusText
:
'
Not found
'
,
error
:
'
not_found
'
,
message
:
'
Document not found.
'
,
reason
:
'
Document with specified id does not exist
'
});
return
;
}
// 409
if
(
doc
.
_rev
!==
prev_rev
)
{
// want to update an older document
that
.
error
({
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
message
:
'
Document update conflict.
'
,
reason
:
'
Trying to update a previous document version
'
});
return
;
}
// check attachment id
attmtid
=
command
.
getAttachmentId
();
if
(
attmtid
)
{
attmtpath
=
docpath
+
'
/
'
+
attmtid
;
attmt
=
localstorage
.
getItem
(
attmtpath
);
// create _attachments
if
(
doc
.
_attachments
===
undefined
){
doc
.
_attachments
=
{};
}
}
}
// create _attachments object for this attachment
if
(
doc
.
_attachments
[
attmtid
]
===
undefined
){
doc
.
_attachments
[
attmtid
]
=
{};
}
else
{
// 404 revision supplied is not on tree
that
.
error
(
utilities
.
throwError
(
404
,
'
Document not found, please check revision
'
)
);
return
;
}
// set revpos
doc
.
_attachments
[
attmtid
].
revpos
=
parseInt
(
doc
.
_rev
.
split
(
'
-
'
)[
0
],
10
);
// store/update attachment
localstorage
.
setItem
(
attmtpath
,
command
.
getContent
());
}
else
{
// no attachment id specified
that
.
error
({
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
message
:
'
Document update conflict.
'
,
reason
:
'
No attachment id specified
'
});
return
;
}
// rev = [number, hash]
rev
=
utilities
.
generateNextRevision
(
prev_rev
,
''
+
doc
+
'
'
+
now
+
''
);
doc
.
_rev
=
rev
.
join
(
'
-
'
);
doc
.
_revisions
.
ids
.
unshift
(
rev
[
1
]);
doc
.
_revisions
.
start
=
rev
[
0
];
doc
.
_revs_info
[
0
].
status
=
'
deleted
'
;
doc
.
_revs_info
.
unshift
({
"
rev
"
:
rev
.
join
(
'
-
'
),
"
status
"
:
"
available
"
});
localstorage
.
setItem
(
docpath
,
doc
);
that
.
success
(
priv
.
manageOptions
(
{
"
ok
"
:
true
,
"
id
"
:
docid
,
"
rev
"
:
doc
.
_rev
},
command
,
doc
)
);
});
};
// end putAttachment
...
...
@@ -573,13 +578,14 @@ var newLocalStorage = function ( spec, my ) {
* the user.
* @method allDocs
*/
// ============== NOT MODIFIED YET ===============
that
.
allDocs
=
function
(
command
)
{
setTimeout
(
function
()
{
var
new_array
=
[],
array
=
[],
i
,
l
,
k
=
'
key
'
,
path
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
,
file_object
=
{};
path
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
,
file_object
=
{};
array
=
priv
.
getFileNameArray
();
for
(
i
=
0
,
l
=
array
.
length
;
i
<
l
;
i
+=
1
)
{
...
...
@@ -614,7 +620,7 @@ var newLocalStorage = function ( spec, my ) {
// wait a little in order to simulate asynchronous saving
setTimeout
(
function
()
{
var
docid
,
doc
,
docpath
,
prev_rev
,
attmtid
,
attmt
,
attpath
;
docid
=
command
.
getDocId
()
;
docid
=
command
.
getDocId
()
,
docpath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docid
;
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
);
...
...
src/jio/commands/command.js
View file @
90d37ed6
...
...
@@ -80,6 +80,8 @@ var command = function(spec, my) {
* @return {object} the document.
*/
that
.
getDoc
=
function
()
{
console
.
log
(
"
where is my doc
"
);
console
.
log
(
priv
.
doc
);
return
priv
.
doc
;
};
...
...
test/jiotests.js
View file @
90d37ed6
...
...
@@ -359,10 +359,12 @@ test ('All tests', function () {
_creation_date:10000},'dummyallok loading');
o.jio.get('file',o.f);
o.tick(o);
// remove
o.spy(o,'value',{ok:true,id:"file"},'dummyallok removing');
o.jio.remove({_id:'file'},o.f);
o.tick(o);
// get list
o.spy (o,'value',{
total_rows:2,
...
...
@@ -726,25 +728,37 @@ test ('Post', function(){
test
(
'
Put
'
,
function
(){
// runs following assertions
// 1) PUT without ID = 409
// 2) PUT with wrong ID/rev = 404
// 3) PUT CREATE
// 4) check file was created
// 5) check tree was created
// 6) PUT UPDATE
// 7) check file was replaced
// 8) check tree was updated
// 9) PUT UPDATE 2
// 10) check file was replaced
// 11) check tree was updated
// 12) PUT UPDATE false revision = 409
// 13) SYNC-PUT no revs_info = 409
// 14) SYNC-PUT revs_info
var
o
=
{};
// 1) PUT without ID = 409
// 2) PUT with wrong ID/rev = 404
// 3) PUT CREATE response
// 4) check file was created
// 5) check tree was created
// 6) PUT UPDATE response
// 7) check file was replaced
// 8) check tree was updated
// 9) PUT UPDATE 2 response
// 10) check file was replaced
// 11) check tree was updated
// 12) PUT UPDATE false revision = 409
// 13) SYNC-PUT no revs_info = 409
// 14) SYNC-PUT revs_info response
// 15) check if file created
// 16) check if tree was merged
// 17) SYNC-PUT revs_info dead leaf response
// 18) check that file was NOT created
// 19) check that tree was updated
var
fake_rev_0
,
fake_rev_1
,
fake_rev_2
,
fake_id_0
,
fake_id_1
,
fake_id_2
,
o
=
{};
o
.
t
=
this
;
o
.
clock
=
o
.
t
.
sandbox
.
useFakeTimers
()
,
o
.
falseRevision
,
o
.
clock
=
o
.
t
.
sandbox
.
useFakeTimers
()
;
o
.
falseRevision
;
localstorage
=
{
getItem
:
function
(
item
)
{
return
JSON
.
parse
(
localStorage
.
getItem
(
item
));
...
...
@@ -791,6 +805,8 @@ test ('Put', function(){
"
_rev
"
:
'
1-ABCDEFG
'
},
o
.
f
);
checkReply
(
o
,
null
,
true
);
o
.
clock
.
tick
(
base_tick
);
// start adding content
o
.
jio
.
put
({
"
content
"
:
'
content
'
,
"
_id
"
:
'
myDoc
'
},
function
(
err
,
response
)
{
...
...
@@ -813,9 +829,10 @@ test ('Put', function(){
});
// 3) TEST PUT content
// no idea why this is working for 3/6/9/12, but it does...
checkReply
(
o
,
null
,
true
);
o
.
clock
.
tick
(
base_tick
);
// update document
o
.
jio
.
put
({
"
content
"
:
'
content_modified
'
,
"
_id
"
:
'
myDoc
'
,
"
_rev
"
:
o
.
testRevisionStorage
[
0
]},
...
...
@@ -839,12 +856,13 @@ test ('Put', function(){
// 6) TEST PUT UPDATE
checkReply
(
o
,
null
,
true
);
o
.
clock
.
tick
(
base_tick
);
// update document 2nd time
o
.
jio
.
put
({
"
content
"
:
'
content_modified_again
'
,
"
_id
"
:
'
myDoc
'
,
"
_rev
"
:
o
.
testRevisionStorage
[
0
]},
function
(
err
,
response
)
{
var
fake_rev_0
,
fake_rev_1
,
fake_id_0
,
fake_id_1
;
o
.
spy
(
o
,
'
value
'
,{
"
ok
"
:
true
,
"
id
"
:
response
.
id
,
"
rev
"
:
response
.
rev
},
'
PUT content = ok
'
);
...
...
@@ -867,11 +885,9 @@ test ('Put', function(){
// 9) TEST PUT UPDATE
checkReply
(
o
,
null
,
true
);
// continue to work with this instance
//o.jio.stop();
//o.clean;
o
.
clock
.
tick
(
base_tick
);
//
try updating with
false revision
//
TEST 12) PUT
false revision
o
.
spy
(
o
,
'
value
'
,{
"
error
"
:
'
conflict
'
,
"
message
"
:
'
Document update conflict.
'
,
...
...
@@ -884,11 +900,11 @@ test ('Put', function(){
o
.
jio
.
put
({
"
content
"
:
'
content_modified_false
'
,
"
_id
"
:
'
myDoc
'
,
"
_rev
"
:
o
.
falseRevision
},
o
.
f
);
// TEST 12) PUT false revision
checkReply
(
o
,
null
,
true
);
o
.
clock
.
tick
(
base_tick
);
//
try updating without
revs_info
//
TEST 13) SYNC-PUT no
revs_info
o
.
spy
(
o
,
'
value
'
,{
"
error
"
:
'
conflict
'
,
"
message
"
:
'
Document update conflict.
'
,
...
...
@@ -901,9 +917,10 @@ test ('Put', function(){
o
.
jio
.
put
({
"
content
"
:
'
content_modified_false
'
,
"
_id
"
:
'
myDoc
'
,
"
_rev
"
:
'
1-abcdefg
'
},
o
.
f
);
// TEST 13) SYNC-PUT no revs_info
checkReply
(
o
,
null
,
true
);
o
.
clock
.
tick
(
base_tick
);
// add a new document version with fake revs_info
// the new document has the same origin and first edit,
// then it was changed to a new version (3-a9d...),
...
...
@@ -912,10 +929,12 @@ test ('Put', function(){
// and add the two new dummy revisions into the final
// tree. Also the new document should be stored
// in local storage.
fake_rev_2
=
o
.
testRevisionStorage
[
2
];
fake_rev_1
=
o
.
testRevisionStorage
[
1
];
fake_rev_0
=
o
.
testRevisionStorage
[
0
];
fake_id_
0
=
o
.
testRevisionStorage
[
0
].
split
(
'
-
'
)[
1
];
fake_id_
2
=
o
.
testRevisionStorage
[
2
].
split
(
'
-
'
)[
1
];
fake_id_1
=
o
.
testRevisionStorage
[
1
].
split
(
'
-
'
)[
1
];
fake_id_0
=
o
.
testRevisionStorage
[
0
].
split
(
'
-
'
)[
1
];
// put a new document version
o
.
jio
.
put
({
...
...
@@ -927,7 +946,7 @@ test ('Put', function(){
{
"
rev
"
:
"
3-a9dac9ff5c8e1b2fce58e5397e9b6a8de729d5c6eff8f26a7b71df6348986123
"
,
"
status
"
:
"
deleted
"
},
{
"
rev
"
:
fake_rev_1
,
"
status
"
:
"
deleted
"
},
{
"
rev
"
:
fake_rev_0
,
"
status
"
:
"
deleted
"
}
],
],
"
_revisions
"
:{
"
start
"
:
4
,
"
ids
"
:[
...
...
@@ -970,7 +989,80 @@ test ('Put', function(){
// 14) TEST PUT UPDATE
checkReply
(
o
,
null
,
true
);
o
.
clock
.
tick
(
base_tick
);
/*
// put a new deleted version
o.jio.put({
"content":'a_deleted_version',
"_id":'myDoc',
"_rev":"3-05210795b6aa8cb5e1e7f021960d233cf963f1052b1a41777ca1a2aff8fd4b61",
"_revs_info":[
{"rev":"3-05210795b6aa8cb5e1e7f021960d233cf963f1052b1a41777ca1a2aff8fd4b61","status":"deleted"},
{"rev":"2-67ac10df5b7e2582f2ea2344b01c68d461f44b98fef2c5cba5073cc3bdb5a844","status":"deleted"},
{"rev":fake_rev_2,"status":"deleted"}
],
"_revisions":{
"start":3,
"ids":[
"05210795b6aa8cb5e1e7f021960d233cf963f1052b1a41777ca1a2aff8fd4b61",
"67ac10df5b7e2582f2ea2344b01c68d461f44b98fef2c5cba5073cc3bdb5a844",
fake_id_2
]}
},
function(err, response) {
//o.testRevisionStorage.unshift(response.rev);
o.buildTestTree = {
"kids":[{
"kids":[
{"kids":[],
"rev":o.testRevisionStorage[0],
"status":'available',
"type":'leaf'
},
{"kids":[{
"kids":[],
"rev":"4-b5bb2f1657ac5ac270c14b2335e51ef1ffccc0a7259e14bce46380d6c446eb89",
"status":'available', "type":'leaf'
}],
"rev":"3-a9dac9ff5c8e1b2fce58e5397e9b6a8de729d5c6eff8f26a7b71df6348986123",
"status":'deleted',
"type":'branch'
}],
"rev":o.testRevisionStorage[1],
"status":'deleted',
"type":'branch'
},{
"kids":[
{
"kids":[],
"rev":"3-05210795b6aa8cb5e1e7f021960d233cf963f1052b1a41777ca1a2aff8fd4b61",
"status":'deleted',
"type":'leaf'
}],
"rev":"2-67ac10df5b7e2582f2ea2344b01c68d461f44b98fef2c5cba5073cc3bdb5a844",
"status":'deleted',
"typ":'branch'
}],
"rev":o.testRevisionStorage[2],
"status":'deleted',
"type":'branch'
};
o.spy(o,'value',{"ok":true,"id":response.id,
"rev":response.rev}, 'PUT SYNC dead leaf = ok');
o.f(response);
// TEST 18) check document was stored
//checkFile(response, o, null, true);
// TEST 19) check tree was updated
//checkTreeNode(response, o, null, true);
});
// 17) TEST PUT UPDATE
//checkReply(o,null,true);
*/
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment