docs: function Engine(sqlfilepath,callback) {                                                      
  	this._resourceFields={};
  	this._tags={};
  	this._db=new TransactionDatabase( new sqlite3.Database(sqlfilepath) );
  
  	var self=this;
  	self._db.run("CREATE TABLE tag (name TEXT PRIMARY KEY, resource_count INTEGER, last_used_at INTEGER)",[], (err) => {
  		self._db.serialize( () => {
  			if (!err) {
  				/* 
  				if no error, the table did not exist, so let's create the remaining tables since this db is not yet initialized
  				*/
  				
  				/*
  				following line is commented since i get foreign key errors although i shouldn't. 
  				there must be some subtility i miss in parallel operations, although they appear to run
  				all in the correct order. i finally don't care too much, since the code ensures consistency 
  				pretty much by its own.
  				*/
  				//self._db.run("PRAGMA foreign_keys = '1'");
  				self._db.run("CREATE TABLE resource (_url TEXT, _created_at INTEGER, _modified_at INTEGER, _path TEXT)");
  				self._db.run("CREATE UNIQUE INDEX resource_path on resource (_path)");
  				self._db.run("CREATE TABLE tree_idx (desc_id INTEGER, anc_id INTEGER, FOREIGN KEY (anc_id) REFERENCES resource (rowid), FOREIGN KEY (desc_id) REFERENCES resource (rowid))");
  				self._db.run("CREATE UNIQUE INDEX tree_descendant on tree_idx (desc_id,anc_id)");
  				self._db.run("CREATE INDEX tree_ancestor on tree_idx (anc_id)");
  				self._db.run("CREATE TABLE resource_field (name TEXT, type INTEGER)");
  				self._db.run("CREATE TABLE resource_tag (resource_id INTEGER, tag_id INTEGER, tag_path TEXT, comment TEXT, FOREIGN KEY (resource_id) REFERENCES resource (rowid), FOREIGN KEY (tag_id) REFERENCES tag (rowid))");
  				self._db.run("CREATE UNIQUE INDEX resource_tag_relation on resource_tag (resource_id,tag_id)");
  				self._db.run("CREATE INDEX resource_tag_by_tag on resource_tag (tag_id)");
  				self._db.run("CREATE INDEX resource_tag_by_tagpath on resource_tag (tag_path)");
  				self._db.run("CREATE TABLE meta (key TEXT, value TEXT)");
  				self._db.run("INSERT INTO meta (key,value) VALUES ('format_version','1')");
  			}
  			/*
  			load all resource fields, which are cached.
  			*/
  			self._db.each("SELECT name,type FROM resource_field", (err, row) => {
  				self._resourceFields[row.name]=row.type;
  			}, (err) => {
  				/*
  				load all tags, which are cached as well.
  				*/
  				self._db.each("SELECT rowid,name,resource_count,last_used_at FROM tag", (err, row) => {
  					self._tags[row.name]=row;
  				}, (err) => {
  					if (callback) callback(err,self);
  				});
  			});
  		});
  	});
  	
  	/*
  	Qed version of the engine API: all public methods of the engine are replicated on the engine.q object, but
  	returning a promise istead of calling a callback.
  	*/
  	this.q={
  		cb: self,
  		define: (fieldName,fieldType) => {
  			var d=Q.defer();
  			self.define(fieldName,fieldType, (err) => {
  				if (err) d.reject(err);
  				else d.resolve();
  			});
  			return d.promise;
  		},
  		loadBulk: (data) => {
  			var d=Q.defer();
  			self.loadBulk(data, (err) => {
  				if (err) d.reject(err);
  				else d.resolve();
  			});
  			return d.promise;
  		},
  		update: (url,tags,data) => {
  			var d=Q.defer();
  			self.update(url,tags,data, (err,id) => {
  				if (err) d.reject(err);
  				else d.resolve(id);
  			});
  			return d.promise;
  		},
  		remove: (url) => {
  			var d=Q.defer();
  			self.remove(url, (err,id) => {
  				if (err) d.reject(err);
  				else d.resolve(id);
  			});
  			return d.promise;
  		},                                   
  		removeBulk: (urlList) => {
  			var d=Q.defer();
  			self.removeBulk(urlList, (err,id) => {
  				if (err) d.reject(err);
  				else d.resolve(id);
  			});
  			return d.promise;
  		},                                   
  		rename: (url,newUrl,renameDescendants) => {
  			var d=Q.defer();
  			self.rename(url, newUrl, renameDescendants, (err,id) => {
  				if (err) d.reject(err);
  				else d.resolve(id);
  			});
  			return d.promise;
  		},
  		findResources: (tags,orderBy,limit,offset) => {
  			var d=Q.defer();
  			self.findResources(tags,orderBy,limit,offset, (err,res) => {
  				if (err) d.reject(err);
  				else d.resolve(res);
  			});
  			return d.promise;
  		},
  		getResource: (url) => {
  			var d=Q.defer();
  			self.getResource(url, (err,res) => {
  				if (err) d.reject(err);
  				else d.resolve(res);
  			});
  			return d.promise;
  		},
  		getBulk: (urlList) => {
  			var d=Q.defer();
  			self.getBulk(urlList, (err,res) => {
  				if (err) d.reject(err);
  				else d.resolve(res);
  			});
  			return d.promise;
  		},
  		tagCloud: (tags,limit,useOr) => {
  			var d=Q.defer();
  			self.tagCloud(tags,limit,useOr, (err,res) => {
  				if (err) d.reject(err);
  				else d.resolve(res);
  			});
  			return d.promise;
  		},
  		getSuggestions: (prefix,exclude,limit,offset,minWeight) => {
  			var d=Q.defer();
  			self.getSuggestions(prefix,exclude,limit,offset,minWeight, (err,res) => {
  				if (err) d.reject(err);
  				else d.resolve(res);
  			});
  			return d.promise;
  		},
  		clear: () => {
  			var d=Q.defer();
  			self.clear( (err,res) => {
  				if (err) d.reject(err);
  				else d.resolve(res);
  			});
  			return d.promise;
  		}
  	};
  	
  	/*
  	ensure that whatever API you are using (the callback API or the Qed one), you will
  	always be able to do:
  		engine.cb.someMethod()
  	and:
  		engine.q.someMethod()
  	getting explicitely the desired version of the method.
  	*/
  	this.q.q=this.q;
  	this.cb=this;
  	
  }