Changes On Branch a01594ff308d121e

Changes In Branch pure-c Excluding Merge-Ins

This is equivalent to a diff from 992994189a to a01594ff30

2020-03-25
00:24
Integrate pure C version check-in: eebfe1f40f user: rkeene tags: trunk
2019-12-06
14:17
Updated ignores Closed-Leaf check-in: a01594ff30 user: rkeene tags: pure-c
2019-12-03
17:59
Made Tcl and C version of "xvfs-create" more similar by re-ordering output check-in: 36d0805e0e user: rkeene tags: pure-c
2019-12-01
00:16
Started work on xvfs-create-c, a pure C version of the builder with no dependencies check-in: ae8437b96b user: rkeene tags: pure-c
2019-11-14
23:39
Revert [ac58551e55], needs more work check-in: 992994189a user: rkeene tags: trunk
23:14
Updated to use Tcl-computed mechanism for building shared objects check-in: ac58551e55 user: rkeene tags: trunk

10
11
12
13
14
15
16


17
18
19
20
21


22
23
24
25
26
27
28
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+
+





+
+







xvfs.so
example-standalone.gcda
example-standalone.gcno
example-flexible.gcda
example-flexible.gcno
example-client.gcda
example-client.gcno
xvfs-create-c.gcda
xvfs-create-c.gcno
xvfs.gcda
xvfs.gcno
xvfs-create-standalone.new
xvfs-create-standalone
xvfs-test-coverage
xvfs-create-c
xvfs-create-c.o
__test__.tcl
sdks
xvfs_random.so
xvfs_synthetic.so
profile-bare
profile-gperf
oprofile_data
Modified Makefile from [fa4437d0b1] to [dafcafb7d8].


1

2
3
4
5
6
7
8
9
10
11
12
13
14







15
16
17
18
19
20
21
1
2

3
4
5
6
7
8
9
10
11
12
13



14
15
16
17
18
19
20
21
22
23
24
25
26
27
+
+
-
+










-
-
-
+
+
+
+
+
+
+







TCLSH_NATIVE  := tclsh
TCL_CONFIG_SH_DIR := $(shell echo 'puts [tcl::pkgconfig get libdir,runtime]' | $(TCLSH_NATIVE))
TCL_CONFIG_SH := /usr/lib64/tclConfig.sh
TCL_CONFIG_SH := $(TCL_CONFIG_SH_DIR)/tclConfig.sh
XVFS_ROOT_MOUNTPOINT := //xvfs:/
CPPFLAGS      := -DXVFS_ROOT_MOUNTPOINT='"$(XVFS_ROOT_MOUNTPOINT)"' -I. -DUSE_TCL_STUBS=1 -DXVFS_DEBUG $(shell . "${TCL_CONFIG_SH}" && echo "$${TCL_INCLUDE_SPEC}") $(XVFS_ADD_CPPFLAGS)
CFLAGS        := -fPIC -g3 -ggdb3 -Wall $(XVFS_ADD_CFLAGS)
LDFLAGS       := $(XVFS_ADD_LDFLAGS)
LIBS          := $(shell . "${TCL_CONFIG_SH}" && echo "$${TCL_STUB_LIB_SPEC}")
TCLSH         := tclsh
LIB_SUFFIX    := $(shell . "${TCL_CONFIG_SH}"; echo "$${TCL_SHLIB_SUFFIX:-.so}")

all: example-standalone$(LIB_SUFFIX) example-client$(LIB_SUFFIX) example-flexible$(LIB_SUFFIX) xvfs$(LIB_SUFFIX)

example.c: $(shell find example -type f) $(shell find lib -type f) lib/xvfs/xvfs.c.rvt xvfs-create Makefile
	./xvfs-create --directory example --name example > example.c.new
	mv example.c.new example.c
example.c: $(shell find example -type f) $(shell find lib -type f) lib/xvfs/xvfs.c.rvt xvfs-create-c xvfs-create Makefile
	rm -f example.c.new.1 example.c.new.2
	./xvfs-create-c --directory example --name example > example.c.new.1
	./xvfs-create --directory example --name example > example.c.new.2
	bash -c "diff -u <(grep -v '^ *$$' example.c.new.1) <(grep -v '^ *$$' example.c.new.2)" || :
	rm -f example.c.new.2
	mv example.c.new.1 example.c

example-standalone.o: example.c xvfs-core.h xvfs-core.c Makefile
	$(CC) $(CPPFLAGS) -DXVFS_MODE_STANDALONE $(CFLAGS) -o example-standalone.o -c example.c

example-standalone$(LIB_SUFFIX): example-standalone.o Makefile
	$(CC) $(CFLAGS) $(LDFLAGS) -shared -o example-standalone$(LIB_SUFFIX) example-standalone.o $(LIBS)

41
42
43
44
45
46
47






48
49
50
51
52
53
54
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66







+
+
+
+
+
+







# like lib/minirivet, xvfs-core.c, etc) version of "xvfs-create"
xvfs-create-standalone: $(shell find lib -type f) xvfs-create xvfs-core.c xvfs-core.h lib/xvfs/xvfs.c.rvt Makefile
	rm -f xvfs-create-standalone.new xvfs-create-standalone
	./xvfs-create --dump-tcl --remove-debug > xvfs-create-standalone.new
	chmod +x xvfs-create-standalone.new
	mv xvfs-create-standalone.new xvfs-create-standalone

xvfs-create-c: xvfs-create-c.o
	$(CC) $(CFLAGS) $(LDFLAGS) -o xvfs-create-c xvfs-create-c.o $(LIBS)

xvfs-create-c.o: xvfs-create-c.c
	$(CC) $(CPPFLAGS) $(CFLAGS) -o xvfs-create-c.o -c xvfs-create-c.c

xvfs_random$(LIB_SUFFIX): $(shell find example -type f) $(shell find lib -type f) lib/xvfs/xvfs.c.rvt xvfs-create-random Makefile
	./xvfs-create-random | $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DXVFS_MODE_FLEXIBLE -x c - -shared -o xvfs_random$(LIB_SUFFIX) $(LIBS)

xvfs_synthetic$(LIB_SUFFIX): $(shell find lib -type f) lib/xvfs/xvfs.c.rvt xvfs-create-synthetic Makefile
	./xvfs-create-synthetic | $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DXVFS_MODE_FLEXIBLE -x c - -shared -o xvfs_synthetic$(LIB_SUFFIX) $(LIBS)

do-benchmark:
95
96
97
98
99
100
101

102

103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136







+
-
+







+













	./profile-gperf
	gprof ./profile-gperf
	valgrind --tool=callgrind --callgrind-out-file=callgrind.out ./profile-bare 10 2
	callgrind_annotate callgrind.out

clean:
	rm -f xvfs-create-standalone.new xvfs-create-standalone
	rm -f xvfs-create-c.o xvfs-create-c
	rm -f example.c example.c.new
	rm -f example.c example.c.new example.c.new.1 example.c.new.2
	rm -f example-standalone$(LIB_SUFFIX) example-standalone.o
	rm -f example-client.o example-client$(LIB_SUFFIX)
	rm -f example-flexible.o example-flexible$(LIB_SUFFIX)
	rm -f xvfs.o xvfs$(LIB_SUFFIX)
	rm -f example-standalone.gcda example-standalone.gcno
	rm -f example-client.gcda example-client.gcno
	rm -f example-flexible.gcda example-flexible.gcno
	rm -f xvfs-create-c.gcda xvfs-create-c.gcno
	rm -f xvfs_random$(LIB_SUFFIX) xvfs_synthetic$(LIB_SUFFIX)
	rm -f xvfs.gcda xvfs.gcno
	rm -f __test__.tcl
	rm -f profile-bare profile-gperf
	rm -f gmon.out
	rm -f callgrind.out
	rm -rf oprofile_data
	rm -f xvfs-test-coverage.info
	rm -rf xvfs-test-coverage

distclean: clean

.PHONY: all clean distclean test do-test do-coverage do-benchmark do-profile
1







2
3

4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

+
+
+
+
+
+
+

-
+







<?
	# Care must be taken when editing this file as
	# it may be processed by either "xvfs-create"
	# which uses a full Tcl and Rivet parser
	# or by "xvfs-create-c" which uses a much
	# simpler one that only knows about printable
	# sections and ignores all Tcl sections

	if {[info exists ::xvfs::xvfsCoreH]} {
?><?= $::xvfs::xvfsCoreH ?><?
		::minirivet::_emitOutput $::xvfs::xvfsCoreH
	} else {
?>#include <xvfs-core.h><? } ?>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <tcl.h>

51
52
53
54
55
56
57
58
59


60
61
62
63
64
65
66
67
68
69
70
71
72



73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99


100
101
102
103
104
105
106
107
58
59
60
61
62
63
64


65
66

67
68










69
70
71


72
73
74
75
76
77
78
79
80

















81
82

83
84
85
86
87
88
89







-
-
+
+
-


-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-







	} data;
};
#endif

<?
	package require xvfs

	xvfs::main $::xvfs::argv

	set ::xvfs::fileInfoStruct [xvfs::main $::xvfs::argv]
?><?= $::xvfs::fileInfoStruct ?>
?>
static long xvfs_<?= $::xvfs::fsName ?>_nameToIndex(const char *path) {
<?
		if {[llength $::xvfs::outputFiles] < 3} {
			set hashMode perfectHashFunction
		} else {
			set hashMode hashTable
		}

		if {$hashMode eq "hashTable"} {
			set hashTable [::xvfs::generateHashTable pathIndex path pathLen XVFS_NAME_LOOKUP_ERROR $::xvfs::outputFiles prefix "\t" hashTableSize 30 validate "strcmp(path, xvfs_${::xvfs::fsName}_data\[pathIndex\].name) == 0" onValidated "return(pathIndex);"]
			set hashTableHeader [dict get $hashTable header]
			puts $hashTableHeader
	set hashTable [::xvfs::generateHashTable pathIndex path pathLen XVFS_NAME_LOOKUP_ERROR $::xvfs::outputFiles prefix "\t" hashTableSize 30 validate "strcmp(path, xvfs_${::xvfs::fsName}_data\[pathIndex\].name) == 0" onValidated "return(pathIndex);"]
	set hashTableHeader [dict get $hashTable header]
?><?= $hashTableHeader ?>
		}
?>	long pathIndex;
	long pathIndex;
	ssize_t pathLen;

	if (path == NULL) {
		return(XVFS_NAME_LOOKUP_ERROR);
	}

	pathLen = strlen(path);

<?
		if {$hashMode eq "perfectHashFunction"} {
?>
	pathIndex = <?= [::xvfs::generatePerfectHashFunctionCall "path" pathLen XVFS_NAME_LOOKUP_ERROR $::xvfs::outputFiles] ?>;
	if (pathIndex < 0 || pathIndex >= <?= [llength $::xvfs::outputFiles] ?>) {
		pathIndex = XVFS_NAME_LOOKUP_ERROR;
	}

	if (pathIndex != XVFS_NAME_LOOKUP_ERROR) {
		if (strcmp(path, xvfs_<?= $::xvfs::fsName ?>_data[pathIndex].name) == 0) {
			return(pathIndex);
		}
	}
<?
		} else {
			puts [dict get $hashTable body]
		}
<?= [dict get $hashTable body] ?>

?>
	return(XVFS_NAME_LOOKUP_ERROR);
}

static const char **xvfs_<?= $::xvfs::fsName ?>_getChildren(const char *path, Tcl_WideInt *count) {
	const struct xvfs_file_data *fileInfo;
	long inode;

214
215
216
217
218
219
220
221
222


223
224
225
226
227
228
229
196
197
198
199
200
201
202


203
204
205
206
207
208
209
210
211







-
-
+
+







	inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
	if (inode == XVFS_NAME_LOOKUP_ERROR) {
		return(XVFS_RV_ERR_ENOENT);
	}
	
	fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
	
	statBuf->st_dev   = <?= [zlib adler32 $::xvfs::fsName] ?>;
	statBuf->st_rdev  = <?= [zlib adler32 $::xvfs::fsName] ?>;
	statBuf->st_dev   = <?= [zlib adler32 $::xvfs::fsName 0] ?>;
	statBuf->st_rdev  = <?= [zlib adler32 $::xvfs::fsName 0] ?>;
	statBuf->st_ino   = inode;
	statBuf->st_uid   = 0;
	statBuf->st_gid   = 0;
	statBuf->st_atime = 0;
	statBuf->st_ctime = 0;
	statBuf->st_mtime = 0;
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9




10

11
12
13
14
15
16
17









-
-
-
-
+
-







#! /usr/bin/env tclsh

namespace eval ::xvfs {}
namespace eval ::xvfs::callback {}

set ::xvfs::_xvfsDir [file dirname [info script]]

# Functions
proc ::xvfs::_emitLine {line} {
	if {[info command ::minirivet::_emitOutput] ne ""} {
		::minirivet::_emitOutput "${line}\n"
	} else {
		puts $line
	lappend ::xvfs::_emitLine $line
	}
}

proc ::xvfs::printHelp {channel {errors ""}} {
	if {[llength $errors] != 0} {
		foreach error $errors {
			puts $channel "error: $error"
		}
127
128
129
130
131
132
133
134
135
136
137

138
139
140

141
142

143
144
145
146
147
148
149
123
124
125
126
127
128
129

130
131

132
133
134

135
136
137
138
139
140
141
142
143
144
145







-


-
+


-
+


+







			return -code error "Unable to process $inputFile, unknown type: $fileInfo(type)"
		}
	}

	::xvfs::_emitLine "\t\{"
	::xvfs::_emitLine "\t\t.name = \"[sanitizeCString $outputFile]\","
	::xvfs::_emitLine "\t\t.type = $type,"
	::xvfs::_emitLine "\t\t.size = $size,"
	switch -exact -- $fileInfo(type) {
		"file" {
			::xvfs::_emitLine "\t\t.data.fileContents = (const unsigned char *) $data"
			::xvfs::_emitLine "\t\t.data.fileContents = (const unsigned char *) $data,"
		}
		"directory" {
			::xvfs::_emitLine "\t\t.data.dirChildren  = $children"
			::xvfs::_emitLine "\t\t.data.dirChildren  = $children,"
		}
	}
	::xvfs::_emitLine "\t\t.size = $size"
	::xvfs::_emitLine "\t\},"
}

proc ::xvfs::processDirectory {fsName directory {subDirectory ""}} {
	set subDirectories [list]
	set outputFiles [list]
	set workingDirectory [file join $directory $subDirectory]
278
279
280
281
282
283
284



285
286
287
288
289
290
291
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290







+
+
+







	}

	## 3. Start processing directory and producing initial output
	set ::xvfs::outputFiles [processDirectory $fsName $rootDirectory]

	set ::xvfs::fsName $fsName
	set ::xvfs::rootDirectory $rootDirectory

	# Return the output
	return [join $::xvfs::_emitLine "\n"]
}

proc ::xvfs::run {args} {
	uplevel #0 { package require minirivet }

	set ::xvfs::argv $args
	::minirivet::parse [file join $::xvfs::_xvfsDir xvfs.c.rvt]
Added xvfs-create-c.c version [8abf7d803b].
17
18
19
20
21
22
23








24
25
26
27
28
29
30
31



32
33
34
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44







+
+
+
+
+
+
+
+







-
+
+
+



	fileContents "abc"
}
dict set ::myOwnVFS "xvfs-create-synthetic" {
	type file
}

proc ::xvfs::callback::addOutputFiles {fsName} {
	for {set i 0} {$i < 100000} {incr i} {
		set filename [expr rand()]
		::xvfs::processFile $fsName "" $filename [dict create type file fileContents [expr rand()]]
		lappend retval $filename
	}

	dict set ::myOwnVFS "" children [list foo xvfs-create-synthetic {*}$retval]

	dict for {outputName fileContentsDict} $::myOwnVFS {
		set inputFile $outputName
		if {[dict exists $fileContentsDict inputFile]} {
			set inputFile [dict get $fileContentsDict inputFile]
		}
		::xvfs::processFile $fsName $inputFile $outputName $fileContentsDict
	}
	return [dict keys $::myOwnVFS]
	lappend retval {*}[dict keys $::myOwnVFS]

	return $retval
}

::xvfs::run --directory [pwd] --name synthetic
14
15
16
17
18
19
20
21

22
23
24
25
14
15
16
17
18
19
20

21
22
23
24
25







-
+




	lappend list $i
}

for {set idx 0} {$idx < [llength $list]} {incr idx} {
	set subList [lrange $list 0 $idx]
	puts "$idx ($subList):"
	puts [time {
		puts [::xvfs::generatePerfectHashFunctionCall pathName strlen(pathName) -1 $subList triesAtHashSize 1]
		puts [::xvfs::generatePerfectHashFunctionCall pathName strlen(pathName) -1 $subList useCacheFirst true]
	} 1]
	puts ""
}