Commits

Ivan Voras committed 8d722ee Draft

Initial version with Kyoto Cabinet

Comments (0)

Files changed (1)

 #include <err.h>
 #include <errno.h>
 #include <assert.h>
+#include <libutil.h>
 
 #include <kclangc.h>
 #include <yaml.h>
 static int unit = G_GATE_UNIT_AUTO;
 static unsigned flags = 0;
 static int force = 0;
-static unsigned sectorsize = 0;
+static unsigned sectorsize = 4096;
+static off_t mediasize = 10LL*1024*1024*1024;
 static unsigned timeout = G_GATE_TIMEOUT;
 
 
 {
 
 	fprintf(stderr, "usage: %s create [-v] [-o <ro|wo|rw>] "
-	    "[-s sectorsize] [-t timeout] [-u unit] <path>\n", getprogname());
+	    "[-s sectorsize] [-S mediasize] [-t timeout] [-u unit] <path>\n", getprogname());
 	fprintf(stderr, "       %s rescue [-v] [-o <ro|wo|rw>] <-u unit> "
 	    "<path>\n", getprogname());
 	fprintf(stderr, "       %s destroy [-f] <-u unit>\n", getprogname());
 {
 
 	if ((ggflags & G_GATE_FLAG_READONLY) != 0)
-		return (O_RDONLY);
+		return (KCOREADER);
 	else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0)
-		return (O_WRONLY);
-	return (O_RDWR);
+		return (KCOWRITER);
+	return (KCOREADER | KCOWRITER);
+}
+
+
+static inline int
+format_sector_key(char *key, off_t off)
+{
+	return sprintf(key, "%llx", (unsigned long long)off);
 }
 
 
  * Handles BIO_READ requests from ggate.
  */
 static int
-ggvd_read(int fd, struct g_gate_ctl_io *ggio, size_t *bsize) {
+ggvd_read(KCDB *db, struct g_gate_ctl_io *ggio, size_t *bsize)
+{
 	int error = 0;
+	size_t togo = ggio->gctl_length;
+	off_t off = ggio->gctl_offset;
+	char *data;
+	size_t rsize;
+	char *rbuf;
+	char dbkey[20];
+	int ksize;
 
 	if ((size_t)ggio->gctl_length > *bsize) {
 		ggio->gctl_data = realloc(ggio->gctl_data, ggio->gctl_length);
 		else
 			error = ENOMEM;
 	}
-	if (error == 0) {
-		if (pread(fd, ggio->gctl_data, ggio->gctl_length, ggio->gctl_offset) == -1)
-			error = errno;
+	if (error != 0)
+		return (error);
+
+	if (togo % sectorsize != 0)
+		errx(1, "togo not a multiple of sectorsize");
+
+	data = ggio->gctl_data;
+	while (togo > 0) {
+		ksize = format_sector_key(dbkey, off) + 1;
+		rbuf = kcdbget(db, dbkey, ksize, &rsize);
+		if (rbuf) {
+			if (rsize != sectorsize)
+				errx(1, "rsize != sectorsize: %zu != %u", rsize,
+				    sectorsize);
+			memcpy(data, rbuf, rsize);
+			kcfree(rbuf);
+		} else {
+			memset(data, 0, sectorsize);
+		}
+		togo -= sectorsize;
+		data += sectorsize;
+		off += sectorsize;
 	}
+
 	return (error);
 }
 
  * Handles BIO_WRITE requests from ggate.
  */
 static int
-ggvd_write(int fd, struct g_gate_ctl_io *ggio, size_t *bsize) {
-	if (pwrite(fd, ggio->gctl_data, ggio->gctl_length, ggio->gctl_offset) == -1)
-		return (errno);
+ggvd_write(KCDB *db, struct g_gate_ctl_io *ggio, size_t *bsize)
+{
+	size_t togo = ggio->gctl_length;
+	off_t off = ggio->gctl_offset;
+	char *data = ggio->gctl_data;
+	char dbkey[20];
+	int ksize;
+
+	kcdbbegintran(db, 0);
+	while (togo > 0) {
+		ksize = format_sector_key(dbkey, off) + 1;
+		if (!kcdbset(db, dbkey, ksize, data, sectorsize)) {
+			errx(1, "Error in kcdbset");
+		}
+		togo -= sectorsize;
+		data += sectorsize;
+		off += sectorsize;
+	}
+	kcdbendtran(db, 1);
+
 	return (0);
 }
 
  * Handles BIO_DELETE requests from ggate.
  */
 static int
-ggvd_delete(int fd, struct g_gate_ctl_io *ggio, size_t *bsize) {
-	return ggvd_write(fd, ggio, bsize);
+ggvd_delete(KCDB *db, struct g_gate_ctl_io *ggio, size_t *bsize)
+{
+	size_t togo = ggio->gctl_length;
+	off_t off = ggio->gctl_offset;
+	char dbkey[20];
+	int ksize;
+
+//	kcdbbegintran(db, 1);
+	while (togo > 0) {
+		ksize = format_sector_key(dbkey, off) + 1;
+		if (!kcdbremove(db, dbkey, ksize)) {
+			warnx("Error in kcdbremove");
+		}
+		togo -= sectorsize;
+		off += sectorsize;
+	}
+//	kcdbendtran(db, 1);
+	kcdbsync(db, 1, NULL, NULL);
+
+	return (0);
 }
 
 
 static void
-ggvd_serve(int fd)
+ggvd_serve(KCDB *db)
 {
 	struct g_gate_ctl_io ggio;
 	size_t bsize;
 			/* Exit gracefully. */
 			free(ggio.gctl_data);
 			g_gate_close_device();
-			close(fd);
+			kcdbclose(db);
 			exit(EXIT_SUCCESS);
 		case ENOMEM:
 			/* Buffer too small. */
 
 		switch (ggio.gctl_cmd) {
 		case BIO_READ:
-			error = ggvd_read(fd, &ggio, &bsize);
+			error = ggvd_read(db, &ggio, &bsize);
 			break;
 		case BIO_WRITE:
-			error = ggvd_write(fd, &ggio, &bsize);
+			error = ggvd_write(db, &ggio, &bsize);
 			break;
 		case BIO_DELETE:
-			error = ggvd_delete(fd, &ggio, &bsize);
+			error = ggvd_delete(db, &ggio, &bsize);
 			break;
 		default:
 			error = EOPNOTSUPP;
 ggvd_create(void)
 {
 	struct g_gate_ctl_create ggioc;
-	int fd;
+	KCDB *db = kcdbnew();
 
-	fd = open(path, g_gate_openflags(flags) | O_DIRECT | O_FSYNC);
-	if (fd == -1)
+	if (!kcdbopen(db, path, g_gate_openflags(flags) | KCOCREATE | KCOAUTOTRAN | KCOAUTOSYNC))
 		err(EXIT_FAILURE, "Cannot open %s", path);
+
 	ggioc.gctl_version = G_GATE_VERSION;
 	ggioc.gctl_unit = unit;
-	ggioc.gctl_mediasize = g_gate_mediasize(fd);
-	if (sectorsize == 0)
-		sectorsize = g_gate_sectorsize(fd);
-	if (ggioc.gctl_mediasize % sectorsize != 0)
-		warnx("Device size is not a multiple of sector size: "
+	if (mediasize % sectorsize != 0)
+		errx(1, "Device size is not a multiple of sector size: "
 		    "%jd, %u", (intmax_t)ggioc.gctl_mediasize, sectorsize);
+	ggioc.gctl_mediasize = mediasize;
 	ggioc.gctl_sectorsize = sectorsize;
 	ggioc.gctl_timeout = timeout;
 	ggioc.gctl_flags = flags;
 	if (unit == -1)
 		printf("%s%u\n", G_GATE_PROVIDER_NAME, ggioc.gctl_unit);
 	unit = ggioc.gctl_unit;
-	ggvd_serve(fd);
+	ggvd_serve(db);
 }
 
 static void
 ggvd_rescue(void)
 {
 	struct g_gate_ctl_cancel ggioc;
-	int fd;
+	KCDB *db = kcdbnew();
 
-	fd = open(path, g_gate_openflags(flags));
-	if (fd == -1)
+	if (!kcdbopen(db, path, g_gate_openflags(flags)))
 		err(EXIT_FAILURE, "Cannot open %s", path);
 
 	ggioc.gctl_version = G_GATE_VERSION;
 	ggioc.gctl_seq = 0;
 	g_gate_ioctl(G_GATE_CMD_CANCEL, &ggioc);
 
-	ggvd_serve(fd);
+	ggvd_serve(db);
 }
 
 int
 	for (;;) {
 		int ch;
 
-		ch = getopt(argc, argv, "fo:s:t:u:v");
+		ch = getopt(argc, argv, "fo:s:S:t:u:v");
 		if (ch == -1)
 			break;
 		switch (ch) {
 			if (sectorsize == 0 && errno != 0)
 				errx(EXIT_FAILURE, "Invalid sectorsize.");
 			break;
+		case 'S':
+			if (action != CREATE)
+				usage();
+			if (expand_number(optarg, (uint64_t*)&mediasize) != 0)
+				errx(EXIT_FAILURE, "Invalid mediasize.");
+			break;
 		case 't':
 			if (action != CREATE)
 				usage();