working monitor

This commit is contained in:
skilion 2015-09-17 16:28:24 +02:00
parent e8f7d99653
commit 35c290c4a0
3 changed files with 107 additions and 41 deletions

View file

@ -24,6 +24,7 @@ final class ItemDatabase
{
Database db;
Statement insertItemStmt;
Statement updateItemStmt;
Statement selectItemByIdStmt;
Statement selectItemByParentIdStmt;
@ -44,11 +45,8 @@ final class ItemDatabase
db.exec("CREATE INDEX IF NOT EXISTS name_idx ON item (name)");
db.exec("PRAGMA foreign_keys = ON");
db.exec("PRAGMA recursive_triggers = ON");
//insertItemStmt = db.prepare("INSERT OR REPLACE INTO item (id, name, type, eTag, cTag, mtime, parentId, crc32) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
insertItemStmt = db.prepare("
INSERT OR IGNORE
INTO item (id, name, type, eTag, cTag, mtime, parentId, crc32)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);
insertItemStmt = db.prepare("INSERT OR REPLACE INTO item (id, name, type, eTag, cTag, mtime, parentId, crc32) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
updateItemStmt = db.prepare("
UPDATE item
SET name = ?2, type = ?3, eTag = ?4, cTag = ?5, mtime = ?6, parentId = ?7, crc32 = ?8
WHERE id = ?1
@ -77,6 +75,52 @@ final class ItemDatabase
}
}
void update(const(char)[] id, const(char)[] name, ItemType type, const(char)[] eTag, const(char)[] cTag, const(char)[] mtime, const(char)[] parentId, const(char)[] crc32)
{
with (updateItemStmt) {
bind(1, id);
bind(2, name);
string typeStr = void;
final switch (type) {
case ItemType.file: typeStr = "file"; break;
case ItemType.dir: typeStr = "dir"; break;
}
bind(3, typeStr);
bind(4, eTag);
bind(5, cTag);
bind(6, mtime);
bind(7, parentId);
bind(8, crc32);
exec();
}
}
void upsert(const(char)[] id, const(char)[] name, ItemType type, const(char)[] eTag, const(char)[] cTag, const(char)[] mtime, const(char)[] parentId, const(char)[] crc32)
{
auto s = db.prepare("SELECT COUNT(*) FROM item WHERE id = ?");
s.bind(1, id);
auto r = s.exec();
Statement* p;
if (r.front[0] == "0") p = &insertItemStmt;
else p = &updateItemStmt;
with (p) {
bind(1, id);
bind(2, name);
string typeStr = void;
final switch (type) {
case ItemType.file: typeStr = "file"; break;
case ItemType.dir: typeStr = "dir"; break;
}
bind(3, typeStr);
bind(4, eTag);
bind(5, cTag);
bind(6, mtime);
bind(7, parentId);
bind(8, crc32);
exec();
}
}
// returns a range that go trough all items, depth first
auto selectAll()
{

View file

@ -86,7 +86,11 @@ void main(string[] args)
};
m.onFileChanged = delegate(string path) {
if (verbose) writeln("[M] File changed: ", path);
sync.uploadDifference(path);
try {
sync.uploadDifference(path);
} catch(SyncException e) {
writeln(e.msg);
}
};
m.onDelete = delegate(string path) {
if (verbose) writeln("[M] Item deleted: ", path);

View file

@ -146,8 +146,12 @@ final class SyncEngine
}
}
if (cached) {
itemdb.update(id, name, type, eTag, cTag, mtime, parentId, crc32);
} else {
itemdb.insert(id, name, type, eTag, cTag, mtime, parentId, crc32);
}
Item newItem;
itemdb.insert(id, name, type, eTag, cTag, mtime, parentId, crc32);
itemdb.selectById(id, newItem);
// TODO add item in the db only if correctly downloaded
@ -324,7 +328,25 @@ final class SyncEngine
final switch (item.type) {
case ItemType.file:
if (isFile(item.path)) {
uploadItemDifferences(item);
SysTime localModifiedTime = timeLastModified(item.path);
import core.time: Duration;
item.mtime.fracSecs = Duration.zero; // HACK
if (localModifiedTime != item.mtime) {
if (verbose) writeln("The item last modified time has changed");
string id = item.id;
string eTag = item.eTag;
if (!testCrc32(item.path, item.crc32)) {
if (verbose) writeln("The item content has changed");
writeln("Uploading: ", item.path);
auto res = onedrive.simpleUpload(item.path, item.path, item.eTag);
saveItem(res);
id = res["id"].str;
eTag = res["eTag"].str;
}
uploadLastModifiedTime(id, eTag, localModifiedTime.toUTC());
} else {
if (verbose) writeln("The item has not changed");
}
} else {
if (verbose) writeln("The item was a file but now is a directory");
uploadDeleteItem(item);
@ -347,38 +369,21 @@ final class SyncEngine
}
}
// NOTE: this function works only for files
void uploadDifference(string filename)
void uploadDifference(string path)
{
Item item;
if (itemdb.selectByPath(filename, item)) {
uploadDifference(item);
} else {
uploadNewFile(filename);
}
}
// check if the item is changed and upload the differences
private void uploadItemDifferences(Item item)
{
SysTime localModifiedTime = timeLastModified(item.path);
import core.time: Duration;
item.mtime.fracSecs = Duration.zero; // HACK
if (localModifiedTime != item.mtime) {
if (verbose) writeln("The item last modified time has changed");
string id = item.id;
string eTag = item.eTag;
if (item.type == ItemType.file && !testCrc32(item.path, item.crc32)) {
if (verbose) writeln("The item content has changed");
writeln("Uploading: ", item.path);
auto res = onedrive.simpleUpload(item.path, item.path, item.eTag);
saveItem(res);
id = res["id"].str;
eTag = res["eTag"].str;
try {
Item item;
if (itemdb.selectByPath(path, item)) {
uploadDifference(item);
} else {
if (isDir(path)) {
uploadCreateDir(path);
} else {
uploadNewFile(path);
}
}
uploadLastModifiedTime(id, eTag, localModifiedTime.toUTC());
} else {
if (verbose) writeln("The item has not changed");
} catch (FileException e) {
throw new SyncException(e.msg, e);
}
}
@ -404,7 +409,14 @@ final class SyncEngine
saveItem(res);
string id = res["id"].str;
string eTag = res["eTag"].str;
uploadLastModifiedTime(id, eTag, timeLastModified(path).toUTC());
SysTime mtime;
try {
mtime = timeLastModified(path).toUTC();
} catch (FileException e) {
writeln(e.msg);
return;
}
uploadLastModifiedTime(id, eTag, mtime);
}
private void uploadDeleteItem(Item item)
@ -451,23 +463,29 @@ final class SyncEngine
// swallow exception
}
}
itemdb.insert(id, name, type, eTag, cTag, mtime, parentId, crc32);
itemdb.upsert(id, name, type, eTag, cTag, mtime, parentId, crc32);
}
void uploadMoveItem(const(char)[] from, string to)
{
writeln("Moving remote item: ", from, " -> ", to);
Item item;
if (!itemdb.selectByPath(from, item)) {
if (!itemdb.selectByPath(from, item) || !isItemSynced(item)) {
writeln("Can't move an unsynced item");
return;
}
if (itemdb.selectByPath(to, item)) {
uploadDeleteItem(item);
}
JSONValue diff = ["name": baseName(to)];
diff["parentReference"] = JSONValue([
"path": "/drive/root:/" ~ dirName(to)
]);
auto res = onedrive.updateById(item.id, diff, item.eTag);
saveItem(res);
string id = res["id"].str;
string eTag = res["eTag"].str;
uploadLastModifiedTime(id, eTag, timeLastModified(to).toUTC());
}
void deleteByPath(const(char)[] path)