Skip to content

Instantly share code, notes, and snippets.

@dmatveev
Created June 14, 2011 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmatveev/1025733 to your computer and use it in GitHub Desktop.
Save dmatveev/1025733 to your computer and use it in GitHub Desktop.
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