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; Database db;
Statement insertItemStmt; Statement insertItemStmt;
Statement updateItemStmt;
Statement selectItemByIdStmt; Statement selectItemByIdStmt;
Statement selectItemByParentIdStmt; Statement selectItemByParentIdStmt;
@ -44,11 +45,8 @@ final class ItemDatabase
db.exec("CREATE INDEX IF NOT EXISTS name_idx ON item (name)"); db.exec("CREATE INDEX IF NOT EXISTS name_idx ON item (name)");
db.exec("PRAGMA foreign_keys = ON"); db.exec("PRAGMA foreign_keys = ON");
db.exec("PRAGMA recursive_triggers = 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 REPLACE INTO item (id, name, type, eTag, cTag, mtime, parentId, crc32) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
insertItemStmt = db.prepare(" updateItemStmt = db.prepare("
INSERT OR IGNORE
INTO item (id, name, type, eTag, cTag, mtime, parentId, crc32)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);
UPDATE item UPDATE item
SET name = ?2, type = ?3, eTag = ?4, cTag = ?5, mtime = ?6, parentId = ?7, crc32 = ?8 SET name = ?2, type = ?3, eTag = ?4, cTag = ?5, mtime = ?6, parentId = ?7, crc32 = ?8
WHERE id = ?1 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 // returns a range that go trough all items, depth first
auto selectAll() auto selectAll()
{ {

View file

@ -86,7 +86,11 @@ void main(string[] args)
}; };
m.onFileChanged = delegate(string path) { m.onFileChanged = delegate(string path) {
if (verbose) writeln("[M] File changed: ", 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) { m.onDelete = delegate(string path) {
if (verbose) writeln("[M] Item deleted: ", 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; Item newItem;
itemdb.insert(id, name, type, eTag, cTag, mtime, parentId, crc32);
itemdb.selectById(id, newItem); itemdb.selectById(id, newItem);
// TODO add item in the db only if correctly downloaded // TODO add item in the db only if correctly downloaded
@ -324,7 +328,25 @@ final class SyncEngine
final switch (item.type) { final switch (item.type) {
case ItemType.file: case ItemType.file:
if (isFile(item.path)) { 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 { } else {
if (verbose) writeln("The item was a file but now is a directory"); if (verbose) writeln("The item was a file but now is a directory");
uploadDeleteItem(item); uploadDeleteItem(item);
@ -347,38 +369,21 @@ final class SyncEngine
} }
} }
// NOTE: this function works only for files void uploadDifference(string path)
void uploadDifference(string filename)
{ {
Item item; try {
if (itemdb.selectByPath(filename, item)) { Item item;
uploadDifference(item); if (itemdb.selectByPath(path, item)) {
} else { uploadDifference(item);
uploadNewFile(filename); } else {
} if (isDir(path)) {
} uploadCreateDir(path);
} else {
// check if the item is changed and upload the differences uploadNewFile(path);
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;
} }
uploadLastModifiedTime(id, eTag, localModifiedTime.toUTC()); } catch (FileException e) {
} else { throw new SyncException(e.msg, e);
if (verbose) writeln("The item has not changed");
} }
} }
@ -404,7 +409,14 @@ final class SyncEngine
saveItem(res); saveItem(res);
string id = res["id"].str; string id = res["id"].str;
string eTag = res["eTag"].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) private void uploadDeleteItem(Item item)
@ -451,23 +463,29 @@ final class SyncEngine
// swallow exception // 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) void uploadMoveItem(const(char)[] from, string to)
{ {
writeln("Moving remote item: ", from, " -> ", to); writeln("Moving remote item: ", from, " -> ", to);
Item item; Item item;
if (!itemdb.selectByPath(from, item)) { if (!itemdb.selectByPath(from, item) || !isItemSynced(item)) {
writeln("Can't move an unsynced item"); writeln("Can't move an unsynced item");
return; return;
} }
if (itemdb.selectByPath(to, item)) {
uploadDeleteItem(item);
}
JSONValue diff = ["name": baseName(to)]; JSONValue diff = ["name": baseName(to)];
diff["parentReference"] = JSONValue([ diff["parentReference"] = JSONValue([
"path": "/drive/root:/" ~ dirName(to) "path": "/drive/root:/" ~ dirName(to)
]); ]);
auto res = onedrive.updateById(item.id, diff, item.eTag); auto res = onedrive.updateById(item.id, diff, item.eTag);
saveItem(res); saveItem(res);
string id = res["id"].str;
string eTag = res["eTag"].str;
uploadLastModifiedTime(id, eTag, timeLastModified(to).toUTC());
} }
void deleteByPath(const(char)[] path) void deleteByPath(const(char)[] path)