Filesystem activity producer
Object subclass: ActivityProducer [ | |
| root allEntries actions | | |
ActivityProducer class >> root: aString [ | |
<category: 'instance creation'> | |
^(self new) | |
init: aString; | |
yourself | |
] | |
init: aString [ | |
<category: 'private'> | |
root := File name: aString. | |
allEntries := Set new. | |
] | |
mkName: aString index: anInteger [ | |
<category: 'private'> | |
^anInteger asString, aString, (Random between: 0 and: 1024) asString | |
] | |
createFiles: aBase [ | |
<category: 'private'> | |
(1 to: self numFiles) do: | |
[:i || file name | | |
name := self mkName: 'file' index: i. | |
file := File name: (Directory append: name to: aBase name). | |
file touch. | |
('Created ', file name) log. | |
allEntries add: file] | |
] | |
createTree: level base: aBase [ | |
<category: 'private'> | |
^self createTree: level subdirs: self numSubnodes base: aBase | |
] | |
createTree: level subdirs: numSubtrees base: aBase [ | |
<category: 'private'> | |
level = 0 ifTrue: [^self]. | |
(1 to: numSubtrees) do: | |
[:i || sub name | | |
name := self mkName: 'subdir' index: i. | |
[sub := Directory create: (Directory append: name to: aBase name)] | |
ifError: [^nil]. | |
('Created ', sub name) log. | |
allEntries add: sub. | |
self createTree: level - 1 subdirs: numSubtrees base: sub. | |
self createFiles: sub] | |
] | |
removeTree: aTree [ | |
<category: 'private'> | |
aTree exists ifFalse: [^nil]. | |
aTree subdirs do: [:each | self delete: each]. | |
aTree files do: [:each | self delete: each]. | |
allEntries delete: aTree. | |
aTree remove | |
] | |
removeFile: aFile [ | |
<category: 'private'> | |
aFile remove. | |
allEntries delete: aFile | |
] | |
createTree [ | |
<category: 'private'> | |
self removeTree: root. | |
root := Directory create: root name. | |
self createTree: self treeDepth base: root. | |
] | |
actions [ | |
actions ifNotNil: [^actions]. | |
actions := self actionData inject: #() into: | |
[:acc :each || c | | |
c := OrderedCollection new. | |
(each value * 100) ceiling timesRepeat: [c add: each key]. | |
acc, c]. | |
^actions | |
] | |
randomAction [ | |
| idx | | |
idx := Random between: 1 and: self actions size. | |
^self actions at: idx | |
] | |
produceActivity [ | |
<category: 'execution'> | |
(allEntries randomSubset: 10) do: | |
[:each | each exists ifTrue: | |
[self perform: (self randomAction) with: each. | |
(Delay forMilliseconds: 10) wait]]. | |
] | |
change: aFile [ | |
('Changing ', aFile name) log. | |
aFile isDirectory | |
ifTrue: [self changeDirectory: aFile] | |
ifFalse: [self changeFile: aFile] | |
] | |
changeDirectory: aFile [ | |
self createTree: 1 subdirs: 1 base: aFile | |
] | |
changeFile: aFile [ | |
| s | | |
s := aFile open: FileStream append. | |
s nextPutAll: 'Just a string'; nl. | |
s close | |
] | |
move: aFile [ | |
| newDir newName newFile | | |
[newDir := allEntries detect: [:each | each isDirectory]] ifError: [^nil]. | |
newName := Directory append: aFile stripPath to: newDir name. | |
newFile := File name: newName. | |
[aFile renameTo: newName] ifError: [^nil]. | |
('Moving ', aFile name, ' to ', newName) log. | |
allEntries delete: aFile. | |
allEntries add: newFile. | |
] | |
touch: aFile [ | |
('Touching ', aFile name) log. | |
aFile touch | |
] | |
delete: aFile [ | |
('Removing ', aFile name) log. | |
aFile isDirectory | |
ifTrue: [self removeTree: aFile] | |
ifFalse: [self removeFile: aFile] | |
] | |
run [ | |
<category: 'execution'> | |
self removeTree: root. | |
self createTree. | |
(Delay forSeconds: 10) wait. | |
[(allEntries select: [:each | each exists]) isEmpty] | |
whileFalse: [self produceActivity] | |
] | |
actionData [ | |
<category: 'configuration'> | |
^{#change: -> 0.3. | |
#touch: -> 0.4. | |
#move: -> 0.25. | |
#delete: -> 0.05} | |
] | |
numSubnodes [ | |
<category: 'configuration'> | |
^4 | |
] | |
numFiles [ | |
<category: 'configuration'> | |
^5 | |
] | |
treeDepth [ | |
<category: 'configuration'> | |
^3 | |
] | |
] | |
String extend [ | |
log [ | |
<category: '*producer-logging'> | |
Transcript << self; nl. | |
] | |
] | |
FilePath extend [ | |
subdirs [ | |
<category: '*producer-convenience'> | |
^self directories select: | |
[:each | | |
each path ~= self path and: [each path ~= self parent path]] | |
] | |
] | |
Collection extend [ | |
delete: anObject [ | |
<category: '*producer-convenience'> | |
self remove: anObject ifAbsent: [] | |
] | |
randomSubset: period [ | |
<category: '*producer-convenience'> | |
| magic | | |
magic := Random between: 0 and: period. | |
^self select: [:each | (Random between: 0 and: period) = magic] | |
] | |
] | |
Eval [ | |
| worker | | |
worker := ActivityProducer root: (Smalltalk getArgv: 1). | |
worker run | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment