Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Bryan Kaperick
jio
Commits
f563c978
Commit
f563c978
authored
Aug 06, 2013
by
Tristan Cavelier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
replicaterevisionstorage amd compatible now
parent
286266f6
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
613 additions
and
598 deletions
+613
-598
src/jio.storage/replicaterevisionstorage.js
src/jio.storage/replicaterevisionstorage.js
+613
-598
No files found.
src/jio.storage/replicaterevisionstorage.js
View file @
f563c978
/*jslint indent: 2, maxlen: 80, nomen: true */
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global jIO: true */
/*global jIO, define */
/**
/**
* JIO Replicate Revision Storage.
* JIO Replicate Revision Storage.
* It manages storages that manage revisions and conflicts.
* It manages storages that manage revisions and conflicts.
...
@@ -12,666 +13,680 @@
...
@@ -12,666 +13,680 @@
* ]
* ]
* }
* }
*/
*/
jIO
.
addStorageType
(
'
replicaterevision
'
,
function
(
spec
,
my
)
{
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
module
(
jIO
);
}([
'
jio
'
],
function
(
jIO
)
{
"
use strict
"
;
"
use strict
"
;
var
that
,
priv
=
{};
jIO
.
addStorageType
(
'
replicaterevision
'
,
function
(
spec
,
my
)
{
spec
=
spec
||
{};
var
that
,
priv
=
{};
that
=
my
.
basicStorage
(
spec
,
my
);
spec
=
spec
||
{};
that
=
my
.
basicStorage
(
spec
,
my
);
priv
.
storage_list_key
=
"
storage_list
"
;
priv
.
storage_list_key
=
"
storage_list
"
;
priv
.
storage_list
=
spec
[
priv
.
storage_list_key
];
priv
.
storage_list
=
spec
[
priv
.
storage_list_key
];
priv
.
emptyFunction
=
function
()
{};
priv
.
emptyFunction
=
function
()
{};
that
.
specToStore
=
function
()
{
that
.
specToStore
=
function
()
{
var
o
=
{};
var
o
=
{};
o
[
priv
.
storage_list_key
]
=
priv
.
storage_list
;
o
[
priv
.
storage_list_key
]
=
priv
.
storage_list
;
return
o
;
return
o
;
};
};
/**
/**
* Generate a new uuid
* Generate a new uuid
* @method generateUuid
* @method generateUuid
* @return {string} The new uuid
* @return {string} The new uuid
*/
*/
priv
.
generateUuid
=
function
()
{
priv
.
generateUuid
=
function
()
{
var
S4
=
function
()
{
var
S4
=
function
()
{
var
i
,
string
=
Math
.
floor
(
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
/* 65536 */
Math
.
random
()
*
0x10000
/* 65536 */
).
toString
(
16
);
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
"
0
"
+
string
;
string
=
"
0
"
+
string
;
}
}
return
string
;
return
string
;
};
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
};
};
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
};
/**
/**
* Create an array containing dictionnary keys
* Create an array containing dictionnary keys
* @method dictKeys2Array
* @method dictKeys2Array
* @param {object} dict The object to convert
* @param {object} dict The object to convert
* @return {array} The array of keys
* @return {array} The array of keys
*/
*/
priv
.
dictKeys2Array
=
function
(
dict
)
{
priv
.
dictKeys2Array
=
function
(
dict
)
{
var
k
,
newlist
=
[];
var
k
,
newlist
=
[];
for
(
k
in
dict
)
{
for
(
k
in
dict
)
{
if
(
dict
.
hasOwnProperty
(
k
))
{
if
(
dict
.
hasOwnProperty
(
k
))
{
newlist
.
push
(
k
);
newlist
.
push
(
k
);
}
}
}
}
return
newlist
;
return
newlist
;
};
};
/**
/**
* Checks a revision format
* Checks a revision format
* @method checkRevisionFormat
* @method checkRevisionFormat
* @param {string} revision The revision string
* @param {string} revision The revision string
* @return {boolean} True if ok, else false
* @return {boolean} True if ok, else false
*/
*/
priv
.
checkRevisionFormat
=
function
(
revision
)
{
priv
.
checkRevisionFormat
=
function
(
revision
)
{
return
(
/^
[
0-9
]
+-
[
0-9a-zA-Z_
]
+$/
.
test
(
revision
));
return
(
/^
[
0-9
]
+-
[
0-9a-zA-Z_
]
+$/
.
test
(
revision
));
};
};
/**
/**
* Clones an object in deep (without functions)
* Clones an object in deep (without functions)
* @method clone
* @method clone
* @param {any} object The object to clone
* @param {any} object The object to clone
* @return {any} The cloned object
* @return {any} The cloned object
*/
*/
priv
.
clone
=
function
(
object
)
{
priv
.
clone
=
function
(
object
)
{
var
tmp
=
JSON
.
stringify
(
object
);
var
tmp
=
JSON
.
stringify
(
object
);
if
(
tmp
===
undefined
)
{
if
(
tmp
===
undefined
)
{
return
undefined
;
return
undefined
;
}
}
return
JSON
.
parse
(
tmp
);
return
JSON
.
parse
(
tmp
);
};
};
/**
/**
* Like addJob but also return the method and the index of the storage
* Like addJob but also return the method and the index of the storage
* @method send
* @method send
* @param {string} method The request method
* @param {string} method The request method
* @param {number} index The storage index
* @param {number} index The storage index
* @param {object} doc The document object
* @param {object} doc The document object
* @param {object} option The request object
* @param {object} option The request object
* @param {function} callback The callback. Parameters:
* @param {function} callback The callback. Parameters:
* - {string} The request method
* - {string} The request method
* - {number} The storage index
* - {number} The storage index
* - {object} The error object
* - {object} The error object
* - {object} The response object
* - {object} The response object
*/
*/
priv
.
send
=
function
(
method
,
index
,
doc
,
option
,
callback
)
{
priv
.
send
=
function
(
method
,
index
,
doc
,
option
,
callback
)
{
var
wrapped_callback_success
,
wrapped_callback_error
;
var
wrapped_callback_success
,
wrapped_callback_error
;
callback
=
callback
||
priv
.
emptyFunction
;
callback
=
callback
||
priv
.
emptyFunction
;
wrapped_callback_success
=
function
(
response
)
{
wrapped_callback_success
=
function
(
response
)
{
callback
(
method
,
index
,
undefined
,
response
);
callback
(
method
,
index
,
undefined
,
response
);
};
wrapped_callback_error
=
function
(
err
)
{
callback
(
method
,
index
,
err
,
undefined
);
};
that
.
addJob
(
method
,
priv
.
storage_list
[
index
],
doc
,
option
,
wrapped_callback_success
,
wrapped_callback_error
);
};
};
wrapped_callback_error
=
function
(
err
)
{
callback
(
method
,
index
,
err
,
undefined
);
/**
* Use "send" method to all sub storages.
* Calling "callback" for each storage response.
* @method sendToAll
* @param {string} method The request method
* @param {object} doc The document object
* @param {object} option The request option
* @param {function} callback The callback. Parameters:
* - {string} The request method
* - {number} The storage index
* - {object} The error object
* - {object} The response object
*/
priv
.
sendToAll
=
function
(
method
,
doc
,
option
,
callback
)
{
var
i
;
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
priv
.
send
(
method
,
i
,
doc
,
option
,
callback
);
}
};
};
that
.
addJob
(
/**
* Use "send" method to all sub storages.
* Calling "callback" only with the first response
* @method sendToAllFastestResponseOnly
* @param {string} method The request method
* @param {object} doc The document object
* @param {object} option The request option
* @param {function} callback The callback. Parameters:
* - {string} The request method
* - {object} The error object
* - {object} The response object
*/
priv
.
sendToAllFastestResponseOnly
=
function
(
method
,
method
,
priv
.
storage_list
[
index
],
doc
,
doc
,
option
,
option
,
wrapped_callback_success
,
callback
wrapped_callback_error
)
{
);
var
i
,
callbackWrapper
,
error_count
,
last_error
;
};
error_count
=
0
;
callbackWrapper
=
function
(
method
,
index
,
err
,
response
)
{
/**
if
(
err
)
{
* Use "send" method to all sub storages.
error_count
+=
1
;
* Calling "callback" for each storage response.
last_error
=
err
;
* @method sendToAll
if
(
error_count
===
priv
.
storage_list
.
length
)
{
* @param {string} method The request method
return
callback
(
method
,
err
,
response
);
* @param {object} doc The document object
}
* @param {object} option The request option
* @param {function} callback The callback. Parameters:
* - {string} The request method
* - {number} The storage index
* - {object} The error object
* - {object} The response object
*/
priv
.
sendToAll
=
function
(
method
,
doc
,
option
,
callback
)
{
var
i
;
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
priv
.
send
(
method
,
i
,
doc
,
option
,
callback
);
}
};
/**
* Use "send" method to all sub storages.
* Calling "callback" only with the first response
* @method sendToAllFastestResponseOnly
* @param {string} method The request method
* @param {object} doc The document object
* @param {object} option The request option
* @param {function} callback The callback. Parameters:
* - {string} The request method
* - {object} The error object
* - {object} The response object
*/
priv
.
sendToAllFastestResponseOnly
=
function
(
method
,
doc
,
option
,
callback
)
{
var
i
,
callbackWrapper
,
error_count
,
last_error
;
error_count
=
0
;
callbackWrapper
=
function
(
method
,
index
,
err
,
response
)
{
if
(
err
)
{
error_count
+=
1
;
last_error
=
err
;
if
(
error_count
===
priv
.
storage_list
.
length
)
{
return
callback
(
method
,
err
,
response
);
}
}
callback
(
method
,
err
,
response
);
};
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
priv
.
send
(
method
,
i
,
doc
,
option
,
callbackWrapper
);
}
}
callback
(
method
,
err
,
response
);
};
};
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
priv
.
send
(
method
,
i
,
doc
,
option
,
callbackWrapper
);
}
};
/**
/**
* Use "sendToAll" method, calling "callback" at the last response with
* Use "sendToAll" method, calling "callback" at the last response with
* the response list
* the response list
* @method sendToAllGetResponseList
* @method sendToAllGetResponseList
* @param {string} method The request method
* @param {string} method The request method
* @param {object} doc The document object
* @param {object} doc The document object
* @param {object} option The request option
* @param {object} option The request option
* @return {function} callback The callback. Parameters:
* @return {function} callback The callback. Parameters:
* - {string} The request method
* - {string} The request method
* - {object} The error object
* - {object} The error object
* - {object} The response object
* - {object} The response object
*/
*/
priv
.
sendToAllGetResponseList
=
function
(
method
,
doc
,
option
,
callback
)
{
priv
.
sendToAllGetResponseList
=
function
(
method
,
doc
,
option
,
callback
)
{
var
wrapper
,
callback_count
=
0
,
response_list
=
[],
error_list
=
[];
var
wrapper
,
callback_count
=
0
,
response_list
=
[],
error_list
=
[];
response_list
.
length
=
priv
.
storage_list
.
length
;
response_list
.
length
=
priv
.
storage_list
.
length
;
wrapper
=
function
(
method
,
index
,
err
,
response
)
{
wrapper
=
function
(
method
,
index
,
err
,
response
)
{
error_list
[
index
]
=
err
;
error_list
[
index
]
=
err
;
response_list
[
index
]
=
response
;
response_list
[
index
]
=
response
;
callback_count
+=
1
;
callback_count
+=
1
;
if
(
callback_count
===
priv
.
storage_list
.
length
)
{
if
(
callback_count
===
priv
.
storage_list
.
length
)
{
callback
(
error_list
,
response_list
);
callback
(
error_list
,
response_list
);
}
}
};
priv
.
sendToAll
(
method
,
doc
,
option
,
wrapper
);
};
};
priv
.
sendToAll
(
method
,
doc
,
option
,
wrapper
);
};
/**
* Checks if the sub storage are identical
* @method check
* @param {object} command The JIO command
*/
that
.
check
=
function
(
command
)
{
function
callback
(
err
,
response
)
{
if
(
err
)
{
return
that
.
error
(
err
);
}
that
.
success
(
response
);
}
priv
.
check
(
command
.
cloneDoc
(),
command
.
cloneOption
(),
callback
);
};
/**
/**
* Repair the sub storages to make them identical
* Checks if the sub storage are identical
* @method repair
* @method check
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
repair
=
function
(
command
)
{
that
.
check
=
function
(
command
)
{
function
callback
(
err
,
response
)
{
function
callback
(
err
,
response
)
{
if
(
err
)
{
if
(
err
)
{
return
that
.
error
(
err
);
return
that
.
error
(
err
);
}
that
.
success
(
response
);
}
}
that
.
success
(
response
);
priv
.
check
(
}
command
.
cloneDoc
(),
priv
.
repair
(
command
.
cloneOption
(),
command
.
cloneDoc
(),
callback
command
.
cloneOption
(),
);
true
,
};
callback
);
};
priv
.
check
=
function
(
doc
,
option
,
success
,
error
)
{
priv
.
repair
(
doc
,
option
,
false
,
success
,
error
);
};
priv
.
repair
=
function
(
doc
,
option
,
repair
,
callback
)
{
/**
var
functions
=
{};
* Repair the sub storages to make them identical
callback
=
callback
||
priv
.
emptyFunction
;
* @method repair
option
=
option
||
{};
* @param {object} command The JIO command
functions
.
begin
=
function
()
{
*/
// };
that
.
repair
=
function
(
command
)
{
// functions.repairAllSubStorages = function () {
function
callback
(
err
,
response
)
{
var
i
;
if
(
err
)
{
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
return
that
.
error
(
err
);
priv
.
send
(
}
repair
?
"
repair
"
:
"
check
"
,
that
.
success
(
response
);
i
,
doc
,
option
,
functions
.
repairAllSubStoragesCallback
);
}
}
priv
.
repair
(
command
.
cloneDoc
(),
command
.
cloneOption
(),
true
,
callback
);
};
};
functions
.
repair_sub_storages_count
=
0
;
functions
.
repairAllSubStoragesCallback
=
function
(
method
,
priv
.
check
=
function
(
doc
,
option
,
success
,
error
)
{
index
,
err
,
response
)
{
priv
.
repair
(
doc
,
option
,
false
,
success
,
error
);
if
(
err
)
{
return
that
.
error
(
err
);
}
functions
.
repair_sub_storages_count
+=
1
;
if
(
functions
.
repair_sub_storages_count
===
priv
.
storage_list
.
length
)
{
functions
.
getAllDocuments
(
functions
.
newParam
(
doc
,
option
,
repair
));
}
};
};
functions
.
newParam
=
function
(
doc
,
option
,
repair
)
{
var
param
=
{
priv
.
repair
=
function
(
doc
,
option
,
repair
,
callback
)
{
"
doc
"
:
doc
,
// the document to repair
var
functions
=
{};
"
option
"
:
option
,
callback
=
callback
||
priv
.
emptyFunction
;
"
repair
"
:
repair
,
option
=
option
||
{};
"
responses
"
:
{
functions
.
begin
=
function
()
{
"
count
"
:
0
,
// };
"
list
"
:
[
// functions.repairAllSubStorages = function () {
// 0: response0
var
i
;
// 1: response1
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
// 2: response2
priv
.
send
(
],
repair
?
"
repair
"
:
"
check
"
,
"
stats
"
:
{
i
,
// responseA: [0, 1]
doc
,
// responseB: [2]
option
,
functions
.
repairAllSubStoragesCallback
);
}
};
functions
.
repair_sub_storages_count
=
0
;
functions
.
repairAllSubStoragesCallback
=
function
(
method
,
index
,
err
,
response
)
{
if
(
err
)
{
return
that
.
error
(
err
);
}
functions
.
repair_sub_storages_count
+=
1
;
if
(
functions
.
repair_sub_storages_count
===
priv
.
storage_list
.
length
)
{
functions
.
getAllDocuments
(
functions
.
newParam
(
doc
,
option
,
repair
));
}
};
functions
.
newParam
=
function
(
doc
,
option
,
repair
)
{
var
param
=
{
"
doc
"
:
doc
,
// the document to repair
"
option
"
:
option
,
"
repair
"
:
repair
,
"
responses
"
:
{
"
count
"
:
0
,
"
list
"
:
[
// 0: response0
// 1: response1
// 2: response2
],
"
stats
"
:
{
// responseA: [0, 1]
// responseB: [2]
},
"
stats_items
"
:
[
// 0: [responseA, [0, 1]]
// 1: [responseB, [2]]
],
"
attachments
"
:
{
// attachmentA : {_id: attachmentA, _revs_info, _mimetype: ..}
// attachmentB : {_id: attachmentB, _revs_info, _mimetype: ..}
}
},
},
"
stats_items
"
:
[
"
conflicts
"
:
{
// 0: [responseA, [0, 1]]
// revC: true
// 1: [responseB, [2]]
// revD: true
],
},
"
attachments
"
:
{
"
deal_result_state
"
:
"
ok
"
,
// attachmentA : {_id: attachmentA, _revs_info, _mimetype: ..}
"
my_rev
"
:
undefined
// attachmentB : {_id: attachmentB, _revs_info, _mimetype: ..}
};
param
.
responses
.
list
.
length
=
priv
.
storage_list
.
length
;
return
param
;
};
functions
.
getAllDocuments
=
function
(
param
)
{
var
i
,
doc
=
priv
.
clone
(
param
.
doc
),
option
=
priv
.
clone
(
param
.
option
);
option
.
conflicts
=
true
;
option
.
revs
=
true
;
option
.
revs_info
=
true
;
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
// if the document is not loaded
priv
.
send
(
"
get
"
,
i
,
doc
,
option
,
functions
.
dealResults
(
param
));
}
functions
.
finished_count
+=
1
;
};
functions
.
dealResults
=
function
(
param
)
{
return
function
(
method
,
index
,
err
,
response
)
{
var
response_object
=
{};
if
(
param
.
deal_result_state
!==
"
ok
"
)
{
// deal result is in a wrong state, exit
return
;
}
if
(
err
)
{
if
(
err
.
status
!==
404
)
{
// get document failed, exit
param
.
deal_result_state
=
"
error
"
;
callback
({
"
status
"
:
40
,
"
statusText
"
:
"
Check Failed
"
,
"
error
"
:
"
check_failed
"
,
"
message
"
:
"
An error occured on the sub storage
"
,
"
reason
"
:
err
.
reason
},
undefined
);
return
;
}
}
}
},
// success to get the document
"
conflicts
"
:
{
// add the response in memory
// revC: true
param
.
responses
.
count
+=
1
;
// revD: true
param
.
responses
.
list
[
index
]
=
response
;
},
"
deal_result_state
"
:
"
ok
"
,
// add the conflicting revision for other synchronizations
"
my_rev
"
:
undefined
functions
.
addConflicts
(
param
,
(
response
||
{}).
_conflicts
);
if
(
param
.
responses
.
count
!==
param
.
responses
.
list
.
length
)
{
// this is not the last response, wait for the next response
return
;
}
// this is now the last response
functions
.
makeResponsesStats
(
param
.
responses
);
if
(
param
.
responses
.
stats_items
.
length
===
1
)
{
// the responses are equals!
response_object
.
ok
=
true
;
response_object
.
id
=
param
.
doc
.
_id
;
if
(
doc
.
_rev
)
{
response_object
.
rev
=
doc
.
_rev
;
// "rev": (typeof param.responses.list[0] === "object" ?
// param.responses.list[0]._rev : undefined)
}
callback
(
undefined
,
response_object
);
return
;
}
// the responses are different
if
(
param
.
repair
===
false
)
{
// do not repair
callback
({
"
status
"
:
41
,
"
statusText
"
:
"
Check Not Ok
"
,
"
error
"
:
"
check_not_ok
"
,
"
message
"
:
"
Some documents are different in the sub storages
"
,
"
reason
"
:
"
Storage contents differ
"
},
undefined
);
return
;
}
// repair
functions
.
getAttachments
(
param
);
};
};
};
param
.
responses
.
list
.
length
=
priv
.
storage_list
.
length
;
functions
.
addConflicts
=
function
(
param
,
list
)
{
return
param
;
var
i
;
};
list
=
list
||
[];
functions
.
getAllDocuments
=
function
(
param
)
{
for
(
i
=
0
;
i
<
list
.
length
;
i
+=
1
)
{
var
i
,
doc
=
priv
.
clone
(
param
.
doc
),
option
=
priv
.
clone
(
param
.
option
);
param
.
conflicts
[
list
[
i
]]
=
true
;
option
.
conflicts
=
true
;
option
.
revs
=
true
;
option
.
revs_info
=
true
;
for
(
i
=
0
;
i
<
priv
.
storage_list
.
length
;
i
+=
1
)
{
// if the document is not loaded
priv
.
send
(
"
get
"
,
i
,
doc
,
option
,
functions
.
dealResults
(
param
));
}
functions
.
finished_count
+=
1
;
};
functions
.
dealResults
=
function
(
param
)
{
return
function
(
method
,
index
,
err
,
response
)
{
var
response_object
=
{};
if
(
param
.
deal_result_state
!==
"
ok
"
)
{
// deal result is in a wrong state, exit
return
;
}
}
if
(
err
)
{
};
if
(
err
.
status
!==
404
)
{
functions
.
makeResponsesStats
=
function
(
responses
)
{
// get document failed, exit
var
i
,
str_response
;
param
.
deal_result_state
=
"
error
"
;
for
(
i
=
0
;
i
<
responses
.
count
;
i
+=
1
)
{
str_response
=
JSON
.
stringify
(
responses
.
list
[
i
]);
if
(
responses
.
stats
[
str_response
]
===
undefined
)
{
responses
.
stats
[
str_response
]
=
[];
responses
.
stats_items
.
push
([
str_response
,
responses
.
stats
[
str_response
]
]);
}
responses
.
stats
[
str_response
].
push
(
i
);
}
};
functions
.
getAttachments
=
function
(
param
)
{
var
response
,
parsed_response
,
attachment
;
for
(
response
in
param
.
responses
.
stats
)
{
if
(
param
.
responses
.
stats
.
hasOwnProperty
(
response
))
{
parsed_response
=
JSON
.
parse
(
response
);
for
(
attachment
in
parsed_response
.
_attachments
)
{
if
((
parsed_response
.
_attachments
).
hasOwnProperty
(
attachment
))
{
functions
.
get_attachment_count
+=
1
;
priv
.
send
(
"
getAttachment
"
,
param
.
responses
.
stats
[
response
][
0
],
{
"
_id
"
:
param
.
doc
.
_id
,
"
_attachment
"
:
attachment
,
"
_rev
"
:
JSON
.
parse
(
response
).
_rev
},
param
.
option
,
functions
.
getAttachmentsCallback
(
param
,
attachment
,
param
.
responses
.
stats
[
response
]
)
);
}
}
}
}
};
functions
.
get_attachment_count
=
0
;
functions
.
getAttachmentsCallback
=
function
(
param
,
attachment_id
,
index_list
)
{
return
function
(
method
,
index
,
err
,
response
)
{
if
(
err
)
{
callback
({
callback
({
"
status
"
:
40
,
"
status
"
:
40
,
"
statusText
"
:
"
Check Failed
"
,
"
statusText
"
:
"
Check Failed
"
,
"
error
"
:
"
check_failed
"
,
"
error
"
:
"
check_failed
"
,
"
message
"
:
"
An error occured on the sub storage
"
,
"
message
"
:
"
Unable to retreive attachments
"
,
"
reason
"
:
err
.
reason
"
reason
"
:
err
.
reason
},
undefined
);
},
undefined
);
return
;
return
;
}
}
}
functions
.
get_attachment_count
-=
1
;
// success to get the document
param
.
responses
.
attachments
[
attachment_id
]
=
response
;
// add the response in memory
if
(
functions
.
get_attachment_count
===
0
)
{
param
.
responses
.
count
+=
1
;
functions
.
synchronizeAllSubStorage
(
param
);
param
.
responses
.
list
[
index
]
=
response
;
if
(
param
.
option
.
synchronize_conflicts
!==
false
)
{
functions
.
synchronizeConflicts
(
param
);
// add the conflicting revision for other synchronizations
}
functions
.
addConflicts
(
param
,
(
response
||
{}).
_conflicts
);
if
(
param
.
responses
.
count
!==
param
.
responses
.
list
.
length
)
{
// this is not the last response, wait for the next response
return
;
}
// this is now the last response
functions
.
makeResponsesStats
(
param
.
responses
);
if
(
param
.
responses
.
stats_items
.
length
===
1
)
{
// the responses are equals!
response_object
.
ok
=
true
;
response_object
.
id
=
param
.
doc
.
_id
;
if
(
doc
.
_rev
)
{
response_object
.
rev
=
doc
.
_rev
;
// "rev": (typeof param.responses.list[0] === "object" ?
// param.responses.list[0]._rev : undefined)
}
}
callback
(
undefined
,
response_object
);
};
return
;
}
// the responses are different
if
(
param
.
repair
===
false
)
{
// do not repair
callback
({
"
status
"
:
41
,
"
statusText
"
:
"
Check Not Ok
"
,
"
error
"
:
"
check_not_ok
"
,
"
message
"
:
"
Some documents are different in the sub storages
"
,
"
reason
"
:
"
Storage contents differ
"
},
undefined
);
return
;
}
// repair
functions
.
getAttachments
(
param
);
};
};
};
functions
.
synchronizeAllSubStorage
=
function
(
param
)
{
functions
.
addConflicts
=
function
(
param
,
list
)
{
var
i
,
j
,
len
=
param
.
responses
.
stats_items
.
length
;
var
i
;
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
list
=
list
||
[];
// browsing responses
for
(
i
=
0
;
i
<
list
.
length
;
i
+=
1
)
{
for
(
j
=
0
;
j
<
len
;
j
+=
1
)
{
param
.
conflicts
[
list
[
i
]]
=
true
;
// browsing storage list
}
if
(
i
!==
j
)
{
};
functions
.
synchronizeResponseToSubStorage
(
functions
.
makeResponsesStats
=
function
(
responses
)
{
param
,
var
i
,
str_response
;
param
.
responses
.
stats_items
[
i
][
0
],
for
(
i
=
0
;
i
<
responses
.
count
;
i
+=
1
)
{
param
.
responses
.
stats_items
[
j
][
1
]
str_response
=
JSON
.
stringify
(
responses
.
list
[
i
]);
if
(
responses
.
stats
[
str_response
]
===
undefined
)
{
responses
.
stats
[
str_response
]
=
[];
responses
.
stats_items
.
push
([
str_response
,
responses
.
stats
[
str_response
]
]);
}
responses
.
stats
[
str_response
].
push
(
i
);
}
};
functions
.
getAttachments
=
function
(
param
)
{
var
response
,
parsed_response
,
attachment
;
for
(
response
in
param
.
responses
.
stats
)
{
if
(
param
.
responses
.
stats
.
hasOwnProperty
(
response
))
{
parsed_response
=
JSON
.
parse
(
response
);
for
(
attachment
in
parsed_response
.
_attachments
)
{
if
((
parsed_response
.
_attachments
).
hasOwnProperty
(
attachment
))
{
functions
.
get_attachment_count
+=
1
;
priv
.
send
(
"
getAttachment
"
,
param
.
responses
.
stats
[
response
][
0
],
{
"
_id
"
:
param
.
doc
.
_id
,
"
_attachment
"
:
attachment
,
"
_rev
"
:
JSON
.
parse
(
response
).
_rev
},
param
.
option
,
functions
.
getAttachmentsCallback
(
param
,
attachment
,
param
.
responses
.
stats
[
response
]
)
);
);
}
}
}
}
}
}
}
functions
.
finished_count
-=
1
;
};
};
functions
.
get_attachment_count
=
0
;
functions
.
synchronizeResponseToSubStorage
=
function
(
functions
.
getAttachmentsCallback
=
function
(
param
,
param
,
response
,
attachment_id
,
storage_list
index_list
)
{
)
{
var
i
,
new_doc
,
attachment_to_put
=
[];
return
function
(
method
,
index
,
err
,
response
)
{
if
(
response
===
undefined
)
{
if
(
err
)
{
// no response to sync
callback
({
"
status
"
:
40
,
"
statusText
"
:
"
Check Failed
"
,
"
error
"
:
"
check_failed
"
,
"
message
"
:
"
Unable to retreive attachments
"
,
"
reason
"
:
err
.
reason
},
undefined
);
return
;
return
;
}
}
functions
.
get_attachment_count
-=
1
;
new_doc
=
JSON
.
parse
(
response
);
param
.
responses
.
attachments
[
attachment_id
]
=
response
;
new_doc
.
_revs
=
new_doc
.
_revisions
;
if
(
functions
.
get_attachment_count
===
0
)
{
delete
new_doc
.
_rev
;
functions
.
synchronizeAllSubStorage
(
param
);
delete
new_doc
.
_revisions
;
if
(
param
.
option
.
synchronize_conflicts
!==
false
)
{
delete
new_doc
.
_conflicts
;
functions
.
synchronizeConflicts
(
param
);
for
(
i
in
new_doc
.
_attachments
)
{
}
if
(
new_doc
.
_attachments
.
hasOwnProperty
(
i
))
{
}
attachment_to_put
.
push
({
};
"
_id
"
:
i
,
};
"
_mimetype
"
:
new_doc
.
_attachments
[
i
].
content_type
,
functions
.
synchronizeAllSubStorage
=
function
(
param
)
{
"
_revs_info
"
:
new_doc
.
_revs_info
var
i
,
j
,
len
=
param
.
responses
.
stats_items
.
length
;
});
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
// browsing responses
for
(
j
=
0
;
j
<
len
;
j
+=
1
)
{
// browsing storage list
if
(
i
!==
j
)
{
functions
.
synchronizeResponseToSubStorage
(
param
,
param
.
responses
.
stats_items
[
i
][
0
],
param
.
responses
.
stats_items
[
j
][
1
]
);
}
}
}
}
}
for
(
i
=
0
;
i
<
storage_list
.
length
;
i
+=
1
)
{
functions
.
finished_count
-=
1
;
functions
.
finished_count
+=
attachment_to_put
.
length
||
1
;
};
functions
.
synchronizeResponseToSubStorage
=
function
(
param
,
response
,
storage_list
)
{
var
i
,
new_doc
,
attachment_to_put
=
[];
if
(
response
===
undefined
)
{
// no response to sync
return
;
}
new_doc
=
JSON
.
parse
(
response
);
new_doc
.
_revs
=
new_doc
.
_revisions
;
delete
new_doc
.
_rev
;
delete
new_doc
.
_revisions
;
delete
new_doc
.
_conflicts
;
for
(
i
in
new_doc
.
_attachments
)
{
if
(
new_doc
.
_attachments
.
hasOwnProperty
(
i
))
{
attachment_to_put
.
push
({
"
_id
"
:
i
,
"
_mimetype
"
:
new_doc
.
_attachments
[
i
].
content_type
,
"
_revs_info
"
:
new_doc
.
_revs_info
});
}
}
for
(
i
=
0
;
i
<
storage_list
.
length
;
i
+=
1
)
{
functions
.
finished_count
+=
attachment_to_put
.
length
||
1
;
priv
.
send
(
"
put
"
,
storage_list
[
i
],
new_doc
,
param
.
option
,
functions
.
putAttachments
(
param
,
attachment_to_put
)
);
}
functions
.
finished_count
+=
1
;
functions
.
finished
();
};
functions
.
synchronizeConflicts
=
function
(
param
)
{
var
rev
,
new_doc
,
new_option
;
new_option
=
priv
.
clone
(
param
.
option
);
new_option
.
synchronize_conflict
=
false
;
for
(
rev
in
param
.
conflicts
)
{
if
(
param
.
conflicts
.
hasOwnProperty
(
rev
))
{
new_doc
=
priv
.
clone
(
param
.
doc
);
new_doc
.
_rev
=
rev
;
// no need to synchronize all the conflicts again, do it once
functions
.
getAllDocuments
(
functions
.
newParam
(
new_doc
,
new_option
,
param
.
repair
));
}
}
};
functions
.
putAttachments
=
function
(
param
,
attachment_to_put
)
{
return
function
(
method
,
index
,
err
,
response
)
{
var
i
,
attachment
;
if
(
err
)
{
return
callback
({
"
status
"
:
40
,
"
statusText
"
:
"
Check Failed
"
,
"
error
"
:
"
check_failed
"
,
"
message
"
:
"
Unable to copy attachments
"
,
"
reason
"
:
err
.
reason
},
undefined
);
}
for
(
i
=
0
;
i
<
attachment_to_put
.
length
;
i
+=
1
)
{
attachment
=
{
"
_id
"
:
param
.
doc
.
_id
,
"
_attachment
"
:
attachment_to_put
[
i
].
_id
,
"
_mimetype
"
:
attachment_to_put
[
i
].
_mimetype
,
"
_revs_info
"
:
attachment_to_put
[
i
].
_revs_info
,
// "_revs_info": param.responses.list[index]._revs_info,
"
_data
"
:
param
.
responses
.
attachments
[
attachment_to_put
[
i
].
_id
]
};
priv
.
send
(
priv
.
send
(
"
put
Attachment
"
,
"
put
"
,
index
,
storage_list
[
i
]
,
attachment
,
new_doc
,
option
,
param
.
option
,
functions
.
putAttachment
Callback
(
param
)
functions
.
putAttachment
s
(
param
,
attachment_to_put
)
);
);
}
}
if
(
attachment_to_put
.
length
===
0
)
{
functions
.
finished_count
+=
1
;
functions
.
finished
();
functions
.
finished
();
}
};
};
};
functions
.
synchronizeConflicts
=
function
(
param
)
{
functions
.
putAttachmentCallback
=
function
(
param
)
{
var
rev
,
new_doc
,
new_option
;
return
function
(
method
,
index
,
err
,
response
)
{
new_option
=
priv
.
clone
(
param
.
option
);
if
(
err
)
{
new_option
.
synchronize_conflict
=
false
;
return
callback
(
err
,
undefined
);
for
(
rev
in
param
.
conflicts
)
{
if
(
param
.
conflicts
.
hasOwnProperty
(
rev
))
{
new_doc
=
priv
.
clone
(
param
.
doc
);
new_doc
.
_rev
=
rev
;
// no need to synchronize all the conflicts again, do it once
functions
.
getAllDocuments
(
functions
.
newParam
(
new_doc
,
new_option
,
param
.
repair
));
}
}
}
functions
.
finished
();
};
};
};
functions
.
putAttachments
=
function
(
param
,
attachment_to_put
)
{
functions
.
finished_count
=
0
;
return
function
(
method
,
index
,
err
,
response
)
{
functions
.
finished
=
function
()
{
var
i
,
attachment
;
var
response_object
=
{};
if
(
err
)
{
functions
.
finished_count
-=
1
;
return
callback
({
if
(
functions
.
finished_count
===
0
)
{
"
status
"
:
40
,
response_object
.
ok
=
true
;
"
statusText
"
:
"
Check Failed
"
,
response_object
.
id
=
doc
.
_id
;
"
error
"
:
"
check_failed
"
,
if
(
doc
.
_rev
)
{
"
message
"
:
"
Unable to copy attachments
"
,
response_object
.
rev
=
doc
.
_rev
;
"
reason
"
:
err
.
reason
},
undefined
);
}
for
(
i
=
0
;
i
<
attachment_to_put
.
length
;
i
+=
1
)
{
attachment
=
{
"
_id
"
:
param
.
doc
.
_id
,
"
_attachment
"
:
attachment_to_put
[
i
].
_id
,
"
_mimetype
"
:
attachment_to_put
[
i
].
_mimetype
,
"
_revs_info
"
:
attachment_to_put
[
i
].
_revs_info
,
// "_revs_info": param.responses.list[index]._revs_info,
"
_data
"
:
param
.
responses
.
attachments
[
attachment_to_put
[
i
].
_id
]
};
priv
.
send
(
"
putAttachment
"
,
index
,
attachment
,
option
,
functions
.
putAttachmentCallback
(
param
)
);
}
if
(
attachment_to_put
.
length
===
0
)
{
functions
.
finished
();
}
};
};
functions
.
putAttachmentCallback
=
function
(
param
)
{
return
function
(
method
,
index
,
err
,
response
)
{
if
(
err
)
{
return
callback
(
err
,
undefined
);
}
functions
.
finished
();
};
};
functions
.
finished_count
=
0
;
functions
.
finished
=
function
()
{
var
response_object
=
{};
functions
.
finished_count
-=
1
;
if
(
functions
.
finished_count
===
0
)
{
response_object
.
ok
=
true
;
response_object
.
id
=
doc
.
_id
;
if
(
doc
.
_rev
)
{
response_object
.
rev
=
doc
.
_rev
;
}
callback
(
undefined
,
response_object
);
}
}
callback
(
undefined
,
response_object
)
;
}
;
}
functions
.
begin
();
};
};
functions
.
begin
();
};
/**
/**
* The generic method to use
* The generic method to use
* @method genericRequest
* @method genericRequest
* @param {object} command The JIO command
* @param {object} command The JIO command
* @param {string} method The method to use
* @param {string} method The method to use
*/
*/
that
.
genericRequest
=
function
(
command
,
method
)
{
that
.
genericRequest
=
function
(
command
,
method
)
{
var
doc
=
command
.
cloneDoc
();
var
doc
=
command
.
cloneDoc
();
doc
.
_id
=
doc
.
_id
||
priv
.
generateUuid
();
doc
.
_id
=
doc
.
_id
||
priv
.
generateUuid
();
priv
.
sendToAllFastestResponseOnly
(
priv
.
sendToAllFastestResponseOnly
(
method
,
method
,
doc
,
doc
,
command
.
cloneOption
(),
command
.
cloneOption
(),
function
(
method
,
err
,
response
)
{
function
(
method
,
err
,
response
)
{
if
(
err
)
{
if
(
err
)
{
return
that
.
error
(
err
);
return
that
.
error
(
err
);
}
that
.
success
(
response
);
}
}
that
.
success
(
response
);
);
}
};
);
};
/**
/**
* Post the document metadata to all sub storages
* Post the document metadata to all sub storages
* @method post
* @method post
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
post
=
function
(
command
)
{
that
.
post
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
put
"
);
that
.
genericRequest
(
command
,
"
put
"
);
};
};
/**
/**
* Put the document metadata to all sub storages
* Put the document metadata to all sub storages
* @method put
* @method put
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
put
=
function
(
command
)
{
that
.
put
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
post
"
);
that
.
genericRequest
(
command
,
"
post
"
);
};
};
/**
/**
* Put an attachment to a document to all sub storages
* Put an attachment to a document to all sub storages
* @method putAttachment
* @method putAttachment
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
putAttachment
=
function
(
command
)
{
that
.
putAttachment
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
putAttachment
"
);
that
.
genericRequest
(
command
,
"
putAttachment
"
);
};
};
/**
/**
* Get the document from all sub storages, get the fastest.
* Get the document from all sub storages, get the fastest.
* @method get
* @method get
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
get
=
function
(
command
)
{
that
.
get
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
get
"
);
that
.
genericRequest
(
command
,
"
get
"
);
};
};
/**
/**
* Get the attachment from all sub storages, get the fastest.
* Get the attachment from all sub storages, get the fastest.
* @method getAttachment
* @method getAttachment
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
getAttachment
=
function
(
command
)
{
that
.
getAttachment
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
getAttachment
"
);
that
.
genericRequest
(
command
,
"
getAttachment
"
);
};
};
/**
/**
* Remove the document from all sub storages.
* Remove the document from all sub storages.
* @method remove
* @method remove
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
remove
=
function
(
command
)
{
that
.
remove
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
remove
"
);
that
.
genericRequest
(
command
,
"
remove
"
);
};
};
/**
/**
* Remove the attachment from all sub storages.
* Remove the attachment from all sub storages.
* @method remove
* @method remove
* @param {object} command The JIO command
* @param {object} command The JIO command
*/
*/
that
.
removeAttachment
=
function
(
command
)
{
that
.
removeAttachment
=
function
(
command
)
{
that
.
genericRequest
(
command
,
"
removeAttachment
"
);
that
.
genericRequest
(
command
,
"
removeAttachment
"
);
};
};
return
that
;
return
that
;
});
});
}));
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