Created
June 14, 2011 19:58
-
-
Save dmatveev/1025733 to your computer and use it in GitHub Desktop.
Filesystem activity producer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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