VBScript на службе системного администратора Игорь Орещенков Set oApp = CreateObject ("Shell.Application") ... n = oApp.NameSpace (...).Items.Count + 1 Do ... Loop While oApp.NameSpace (...).Items.Count < n Set oApp = CreateObject ("Shell.Application") Set oNS = oApp.NameSpace (...) ... n = oNS.Items.Count + 1 Do ... Loop While oNS.Items.Count < n ----------------------------------------------------------------------------------------------------------------- Восстановление элементов в Exchangе 2013 без использования резервных копий Сергей Барамба PS> Get-Mailbox s.baramba | Get-MailboxFolderStatistics | sort FolderSize -descending | FT Name, FolderPath, ItemsInFolder PS> Set-Mailbox username -LitigationHoldEnabled $true ----------------------------------------------------------------------------------------------------------------- Кластер виртуализации. Часть 3. Разворачиваем бюджетное отказоустойчивое решение Сергей Урушкин # pcs cluster standby # pcs cluster unstandby # systemctl stop pacemaker # systemctl start pacemaker reboot/shudown/poweroff # systemctl stop pacemaker && poweroff # snmpset -v 1 -c secret 172.16.0.5 .1.3.6.1.4.1.17420.1.2.9.1.13.0 s '1,1,1,1,1,1,1,1' # cp fence_energenie /usr/sbin/fence_energenie # chmod 755 /usr/sbin/fence_energenie # chown root: /usr/sbin/fence_energenie] # rm /etc/dlm/dlm.conf # pcs stonith create fence_vsrv1 fence_energenie \ ipaddr="172.16.0.5" \ community="secret" \ pcmk_host_list="vsrv1" \ port="1" \ delay="0" # pcs stonith create fence_vsrv2 fence_energenie \ ipaddr="172.16.0.5" \ community="secret" \ pcmk_host_list="vsrv2" \ port="2" \ delay="3" # pcs property set stonith-enabled=true # pcs stonith # pcs stonith fence vsrv1 # killall -9 corosync # killall -9 clvmd # poweroff –f ifconfig enp1s0f0 down # drbdadm up r0 # drbdadm disconnect r0 # drbdadm secondary r0 # drbdadm connect --discard-my-data r0 # drbdadm connect r0 # pcs resource cleanup drbd0-ms # pcs resource clear drbd0-ms # cp pcmk_smtp_helper.sh /usr/local/bin # chmod 755 /usr/local/bin/pcmk_smtp_helper.sh # chown root: /usr/local/bin/pcmk_smtp_helper.sh # pcs resource create monitor-smtp ocf:pacemaker:ClusterMon --clone user=root update=30 extra_options="-W -E /usr/local/bin/pcmk_smtp_helper.sh -e root" UserParameter = pacemaker.stopnum, sudo crm_mon -1 | grep 'Stopped' | wc -l UserParameter = pacemaker.failed, sudo crm_mon -1 | grep -q 'Failed' && echo 1 || echo 0 UserParameter = pacemaker.noquorum, sudo crm_mon -1 | grep -q 'WITHOUT quorum' && echo 1 || echo 0 # cat > /etc/sudoers.d/zabbix < service show httpd.service ----------------------------------------------------------------------------------------------------------------- Автоматический мониторинг ошибок в БД Oracle с рассылкой результатов мониторинга по e-mail Владимир Тихомиров; Валерий Михеичев BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name =>’.JOB_ALERTLOG_ERROR' , job_type => 'PLSQL_BLOCK' ,repeat_interval => 'FREQ=MINUTELY; INTERVAL=5' , job_action => ' DECLARE PFILE VARCHAR2(50); BEGIN --имя файла Alert.log в данной БД PFILE:=''alert_ORAIX.log''; P_ALERTLOG_START_JOB(PFILE); END;' , start_date=>SYSDATE , enabled => TRUE); END; } Procedure P_ALERTLOG_READ_ERROR //имя Alert.log файла в БД как входной параметр, т.к. у разных БД имя может быть разным (pfilename varchar2 default 'alert_orasrv.log') is //где ALERTLOG_DIR описывает директорию, где находится файл Alert.log. ALERTLOG_DIR. Путь в директории предварительно создается один раз //запуском PL/SQL-блока, например, в SQL Navigator. Ее автоматическое создание описано далее pfiletype utl_file.file_type; pBuf varchar2(32767); l_file_length number; l_blocksize number; l_exists boolean; pDir varchar2(30):='ALERTLOG_DIR'; Begin //1.Открытие файла Alert.log pfiletype:= UTL_FILE.fopen(pdir, pfilename, open_mode=>'r',max_linesize=>32767); //2. Определение размера файла в байтах. //Запускается процедура UTL_FILE.fgetattr(pDir, pfilename, l_exists, l_file_length, l_blocksize); //Информация о размере файла содержится в l_file_length и сохраняется до следующего запуска JOB //(например, может сохраняться в таблице ошибок ALERTLOG_ERROR в специальной строке, корректируемой при каждом запуске JOB) //3. Чтение файла. Запускается процедура UTL_FILE.FSEEK (pfiletype, l_file_length,32767); //При этом предыдущее значение l_file_length извлекается из места его хранения, подставляясь в указанную выше процедуру. //В силу этого при очередном чтении файла пропускается l_file_length байт в Alert.log, что позволяет читать только //новые строки в Alert.log, поступившие в него за период между запусками JOB //4. Чтение строк из файла Alert.log c записью их в таблицу ALERTLOG_ERROR //При этом пишутся не все строки (строки фильтруются, т.е. не пишутся в таблицу строки, не несущие информации //об ошибках и проблемах, например, такие как not like с набором символов: '%Current log#%', '%Archive log thread%', //'%Checkpoint not complete%', '%Archived%','%Private%', '%Additional%','%backup%', '%Thread%' и т.д.). //Информация о строке извлекается из параметра pbuf процедуры UTL_FILE.get_line(pfiletype,pbuf,32767) в цикле For i in 1..1000000 loop begin UTL_FILE.get_line(pfiletype,pbuf,32767 ); exception when no_data_found then exit; when UTL_FILE.read_error then exit; end; … Insert into ALERTLOG_ERROR Select pbuf,…, sysdate from dual; … End loop; End; select p.value from v$parameter p where p.name like '%user_dump_dest%'; declare pdir varchar(100);str varchar2(100); begin select min(value) into pdir from v$parameter where name='user_dump_dest'; str:='CREATE OR REPLACE DIRECTORY ALERTLOG_DIR AS '''||pdir||''''; execute immediate str; end; Select tablespace_name, round(sum(bytes/1024/1024)) free_mb from dba_free_space group by tablespace_name union all Select tablespace_name, round(free_space/1024/1024) from dba_temp_free_space order by 1 Select status, owner, object_name, object_type, last_ddl_time from dba_objects where status='INVALID' and last_ddl_time>sysdate-1/24 union all select status, owner, index_name, 'INDEX' ,trunc(sysdate,'DD') from dba_indexes i where status='UNUSABLE'; Select c.tablespace_name, checkpoint_time, substr(b.name,1,80) dbf_name, b.file#, round(((a.readtim/decode(a.phyrds,0,1,a.phyblkrd))/100),5) read, round(avg(a.readtim/decode(a.phyrds,0,1,a.phyblkrd)/100) over(),5) avg_read, round((a.writetim/decode(a.phywrts,0,1,a.phyblkwrt)/100),5) writed, round(avg(a.writetim/decode(a.phywrts,0,1,a.phyblkwrt)/100) over(),5) avg_writed from v$datafile b,v$filestat a, sys.dba_data_files c where a.file#=b.file# and b.file#=c.file_id and checkpoint_time>sysdate-1/2 Select trunc(a.first_time,'hh24'), round(sum(a.mb)/1024) redo_gb, round(avg(round(sum(mb)/1024)) over()) avg_read from (select v.first_time, v.creator, round(v.blocks*v.block_size/1024/1024) mb from v$archived_log v) a where a.creator='ARCH' and a.first_time>sysdate-1/2 group by trunc(a.first_time,'hh24') order by 1 Select s.logon_time, s.status, s.sid, s.serial#, s.username, round(v.value/1024/1024) pga_mb from v$sesstat v, v$statname n ,v$session s where n.name='session pga memory' and v.statistic#=n.statistic# and v.sid=s.sid and s.type='USER' and s.logon_time>sysdate-1 order by 6 desc; Select name,value from v$parameter; Select a.ksppinm ,b.ksppstvl ,a.ksppdesc from x$ksppi a,x$ksppcv b,x$ksppsv c where a.indx = b.indx and a.indx = c.indx; Select * from v$lock l2,v$session s2, v$lock l1,v$session s1 where l1.block = 1 and l2.request > 0 and l1.id1 =l2.id1 and l1.id2 = l2.id2 and s1.sid =l1.sid and s2.sid=l2.sid Select * from sys.mon_mods$ m, all_objects o, all_tables t where o.object_name=t.table_name and o.owner=t.owner and o.object_id=m.obj# and o.object_name =’ИМЯ ТАБЛИЦЫ’; Select s.status,a.value open_cursor, s.sql_exec_start, s.sid,s.serial#, s.username,sql_id from v$sesstat a, v$statname b, v$session s where a.statistic# = b.statistic# and s.sid=a.sid and b.name = 'opened cursors current'; Select * from all_indexes where table_owner<>owner Select m.sid, m.session_serial#, m.sql_id,round(m.elapsed_time/1000000) from v$sql_monitor m where round(m.elapsed_time/1000000)>7200 ----------------------------------------------------------------------------------------------------------------- Защита Windows при помощи EMET Сергей Яремчук > EMET_Conf --list > EMET_Conf --list_system > EMET_Conf --set "С:\Program Files\Google\Chrome\Application\chrome.exe" -MandatoryASLR ----------------------------------------------------------------------------------------------------------------- Разбор уязвимости CVE-2014-8609, или Когда можно будет спать спокойно Александр Свириденко import android.app.Service; import android.content.Intent; import android.os.IBinder; public class TestService extends Service { @Override public IBinder onBind(Intent intent) { TestAuthenticator authenticator = new TestAuthenticator(this); return authenticator.getIBinder(); } } public class TestAuthenticator extends AbstractAccountAuthenticator { private final Context mContext; public TestAuthenticator(Context context) { super(context); this.mContext = context; } @Override public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException { return null; } // плюс еще автоматически создастся несколько функций // для реализации интерфейса, которые не играют роли //.. } private void addAccount(String accountType) { Bundle addAccountOptions = new Bundle(); mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(), 0); addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent); addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS, Utils.hasMultipleUsers(this)); AccountManager.get(this).addAccount( accountType, null, /* authTokenType */ null, /* requiredFeatures */ addAccountOptions, null, mCallback, null /* handler */); mAddAccountCalled = true; } PendingIntent pendingIntent = (PendingIntent) options.getParcelable("pendingIntent"); Intent newIntent = new Intent("android.intent.action.MASTER_CLEAR"); try { pendingIntent.send(mContext, 0, newIntent, null, null); } catch (CanceledException e) { e.printStackTrace(); } Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.settings","com.android.settings.accounts.AddAccountSettings")); intent.setAction(Intent.ACTION_RUN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); String authTypes[] = {"com.test"}; intent.putExtra("account_types", authTypes); startActivity(intent); ----------------------------------------------------------------------------------------------------------------- Новое в Tarantool Александр Календарев >./myscript.lua >chmod +x myscript.lua >tarantool ./myscript.lua Пример 1. Создадим файл example1.lua: #!/usr/bin/tarantool print('Hello Word') box.cfg{log_level=3} >print (box.cfg.log_level) >box.cfg.log_level box.cfg{listen=3301} Пример 2. Создадим пространство сессий ses = box.schema.space.create('session') tarantool> ses Пример 3. Создание индексов ses:create_index('primary',{type='hash'}) tarantool> ses ses:create_index('name',{type='tree', parts = {2, 'STR'} }) tarantool>ses.index.name Пример 4. Вставка данных tarantool>ses:insert({1, 'Alex'}) tarantool> ses:insert({2, 'Nataly', 1}) tarantool> ses:insert({3, 'Vitaly', 0}) tarantool> ses:select{3} tarantool> ses:select{} tarantool> ses.index.name:select{'Alex'} // тут обращаемся по номеру индекса tarantool> ses.index[1]:select{'Nataly'} Пример 5. Tarantool & PHP-клиент connect(); $ php example.php tarantool->authenticate('admin', 'admin'); tarantool>box.schema.user.grant('guest','read,write,execute','universe') tarantool>box.schema.user.drop('guest') tarantool>box.schema.user.create('www', {password = '12345'}) tarantool> box.space._user:select{0} $user = array( 5, "Petja", 0); $tnt->insert("ses", $user); $primary_key=9; $user = array( $primary_key, "Yura", 0, array( 'pvp' => 341, 'pvp_level' => 12) ); $tnt->insert("ses", $user); tarantool> box.space.ses:select{9} $key = 2; $tnt->update("ses", $key, array( array( // поле №2 даем новое значение = 3 "field" => 2, "op" => "=", "arg" => 3 ), array( // поле №3 увеличиваем значение +1 "field" => 3, "op" => "+", "arg" => 1 ), ) ); $tarantool->select(имя пр-ва, ключ, индекс, кол-во таплов для вывода, смещение, тип итератора) $level = 10; $index_name = "level"; $tuple = $tnt->select("ses", $level , $index_name , $level); ----------------------------------------------------------------------------------------------------------------- Исследование операции поиска символа в строке (PHP) Игорь Орещенков Листинг 1. Программа тестирования производительности алгоритмов сортировки массивов 1): $m = (int) (($r + $l) / 2); if ($a[$m] >= $c): $r = $m; else: $l = $m; endif; endwhile; return $r < $v and $a[$r] == $c; } } /*========================*/ /* Тестирующая программа. */ /*========================*/ $abc = ''; for ($i = 0; $i < 256; ++$i): $abc .= chr ($i); endfor; $test = new Test (); $test->Go (32, 256, 32); ?> Листинг 2. Программа тестирования методов проверки принадлежности символа множеству 1): $m = (int)(($r + $l) / 2); if ($a[$m] >= $c): $r = $m; else: $l = $m; endif; endwhile; return $r < $v and $a[$r] == $c; } /*------------------------------------------------*/ /* Тестирование бинарного поиска с помощью */ /* функции пользователя (поразрядный сдвиг). */ /*------------------------------------------------*/ protected function Prep3 ($v) { global $abc; global $a, $c; $a = substr ($abc, 0, $v); $c = $abc[0]; } protected function Test3 ($v) { global $a, $c; $l = -1; $r = $v; while ($r - $l > 1): $m = ($r + $l) >> 1; if ($a[$m] >= $c): $r = $m; else: $l = $m; endif; endwhile; return $r < $v and $a[$r] == $c; } /*------------------------------------------------*/ /* Тестирование проверки на попадание в диапазон. */ /*------------------------------------------------*/ protected function Prep4 ($v) { global $abc; global $c, $l, $r; $l = $abc[0]; $r = $abc[$v - 1]; $c = $abc[(int)($v / 2)]; } protected function Test4 ($v) { global $c, $l, $r; return $l <= $c and $c <= $r; } } /*========================*/ /* Тестирующая программа. */ /*========================*/ $abc = ''; for ($i = 0; $i < 256; ++$i): $abc .= chr ($i); endfor; $test = new Test (); $test->Go (32, 256, 32); ?> strpos (ABC . DIGITS, C) !== FALSE strpos (ABC, C) !== FALSE or strpos (DIGITS, C) !== FALSE Листинг 3. Программа тестирования операций конкатенации и дизъюнкции Go (32, 256, 32); ?> ----------------------------------------------------------------------------------------------------------------- Статический анализ типов в JavaScript. Пробуем анализатор Flow от Facebook Александр Майоров $ brew install flow flow --help $> cd flow/examples/01_HelloWorld $> flow check /* @flow */ function foo(x: string, y: number): number { return x.length * y; } foo('Hello', 42); /* @flow */ function length(x) { return x.length; } var total = length('Hello') + length(null); /* @flow */ function length(x) { if (x !== null) { return x.length; } else { return 0; } } var total = length('Hello') + length(null); /* @flow */ function total(numbers: Array) { var result = 0; for (var i = 0; i < numbers.length; i++) { result += numbers[i]; } return result; } total([1, 2, 3, 'Hello']); /* @flow weak */ /* @flow */ function foo(a, b) { return a * b } foo(2, true); [include] /home/otherdir/src [ignore] .*/build/.* [libs] ./lib [options] module.system=node ----------------------------------------------------------------------------------------------------------------- Альтернативы JavaScript от Microsoft и Google Кирилл Сухов npm install -g typescript function greeter(person: string) { return "Hello, " + person; } console.log(greeter("TypeScript")); $ tsc hello.ts function greeter(person) { return "Hello, " + person; } console.log(greeter("TypeScript")); function greeter(person: string){...} greeter(1); $ tsc hello.ts function process(x: number, y: number): number { var sum = x + y; return sum; } function process(x =5, y?: number): number { var sum; if(!y){ sum = x; } else{ sum = x + y; } return sum; } console.log(process(2,6)); //6 console.log(process(2)); //2 console.log(process()); //5 function process(x, y) { if (typeof x === "undefined") { x = 5; } var sum; if (!y) { sum = x; } else { sum = x + y; } return sum; } console.log(process(2, 6)); //8 console.log(process(2)); //2 console.log(process()); //5 class Person { name: string; surname: string; private id: number; static title = "Example"; constructor (name: string, surname: string) { this.name = name; this.surname = surname; } setID (id) { this.id = id; } getFullName () { return this.name+" "+this.surname; } } console.log(Person.title+":"); // Example: var User = new Person("Kirill", "Sukhov"); console.log(User.name); // Kirill console.log(User.getFullName()); // Kirill Sukhov var Person = (function () { function Person(name, surname) { this.name = name; this.surname = surname; } Person.prototype.setID = function (id) { this.id = id; }; Person.prototype.getFullName = function () { return this.name + " " + this.surname; }; Person.title = "Example"; return Person; })(); console.log(Person.title + ":"); // Example: var User = new Person("Kirill", "Sukhov"); console.log(User.name); console.log(User.getFullName()); class Member extends Person { band: string; constructor(name: string, surname: string, band: string){ super(name, surname); this.band = band; } getBand () { return this.band; } } var User = new Member("John", "Lennon", "The Beatles"); console.log(User.getFullName()); // John Lennon console.log(User.getBand()); // The Beatles class Member extends Person { band: string; constructor(name: string, surname: string, band: string){ super(name, surname); this.band = band; } getBand () { return this.band; } getFullName() { return super.getFullName()+" From "+this.band; } } var User = new Member("John", "Lennon", "The Beatles"); console.log(User.getFullName()); // John Lennon from The Beatles interface Band { name: string; state?: string; members: any; } function ShowBand(band: Band) { console.log(band.name); if(band.state){ console.log(band.state); } band.members.forEach( function(member){ console.log(member); }); } var obj = { name: "Focus", state: "nl", members: ["Thijs", "Jan", "Martin", "Hans"] } ShowBand(obj); function ShowBand(band) { console.log(band.name); if (band.state) { console.log(band.state); } band.members.forEach(function (member) { console.log(member); }); } var obj = { name: "Focus", state: "nl", members: ["Thijs", "Jan", "Martin", "Hans"] }; ShowBand(obj); module Say { export function Hello(text: string) { return "Hello " + text; } } console.log(Say.Hello("Module")); var Say; (function (Say) { function Hello(text) { return "Hello " + text; } Say.Hello = Hello; })(Say || (Say = {})); console.log(Say.Hello("Module")); main() { print("Hello Dart"); } $ dart hello.dart $ dart2js hello/bin/hello.dart import 'dart:html'; void main() { querySelector("#sample_text_id") ..text = "Click me!" ..onClick.listen(reverseText); } void reverseText(MouseEvent event) { var text = querySelector("#sample_text_id").text; var buffer = new StringBuffer(); for (int i = text.length - 1; i >= 0; i--) { buffer.write(text[i]); } querySelector("#sample_text_id").text = buffer.toString(); } Helloweb

Helloweb

Hello world from Dart!

Click me!

main() { var d = "Dart"; String w = "World"; print("Hello ${d} ${w}"); } var foo = "Hi"; // объявление без аннотации типа String foo = "Hi"; // объявление с аннотацией типа String final String foo = "Hi"; // объявление с аннотацией типа String и финализацией class Rectangle { var _id; var name; final num height, width; //конструктор (Короткий синтаксис) Rectangle(num this.height, num this.width); // метод num area() { return height * width; } // метод (Короткий синтаксис) num perimeter() => 2*height + 2*width; // акцессоры get id => _id; set id(val) => _id = val; } class Square extends Rectangle { Square(num size) : super(size, size); } var myRect = new Rectangle(3,4); //создает новый экземпляр класса Rectangle myRect.name = "Nice Rectangle"; // Присваиваем значение полю print(myRect.perimeter()); class Shape { num length; num perimeter() => length * 4; } class Square implements Shape { num length; num perimeter() => length * 4; } class Triangle implements Shape { num length; num perimeter() => length * 3; } class Rectangle implements Shape { num length; num width; num perimeter() => length * 2+width*2; } num printPerimetr(Shape shape) { print(shape.perimeter()); } main() { var square = new Square(); square.length = 4; printPerimetr(square); // 16 var triangle = new Triangle(); triangle.length = 4; printPerimetr(triangle); // 12 var rectangle = new Rectangle(); rectangle.length = 4; rectangle.width = 6; printPerimetr(rectangle); // 22 } abstract class iHello { String sayHello(String realise, String name); factory iHello(realise) { return new realise(); } } class RussianHello implements iHello { sayHello(name) { return "Привет $name"; } } void main() { iHello myHello = new iHello(); // var message = myHello.sayHello("Dart"); print(message); // Привет Dart } library animals; part "paint.dart"; class Dog { noise() => paint('BARK!'); } import 'animals.dart'; var fido = new Dog(); import 'animals.dart' as pets; var fido = new pets.Dog(); import "dart:isolate"; void main() { ... analyzeFileList(runSript); } ----------------------------------------------------------------------------------------------------------------- Средства самопознания в Ruby. Что программа на Ruby может знать о самой себе? Иван Шихалев def log msg, file, line $stderr.puts "[#{file}:#{line}] #{msg}" end log 'Сообщение', __FILE__, __LINE__ $ ruby intro01.rb def log msg $stderr.puts "[#{caller[0]}] #{msg}" end def log2 msg cl = caller_locations[0] $stderr.puts "[#{cl.path}:#{cl.lineno}] #{msg}" end log 'Сообщение' log2 'Сообщение' $ ruby intro02.rb def divide a, b if b == 0 || b == 0.0 raise StandardError, 'На ноль делить нельзя', caller end a / b end puts divide(1, 0) $ ruby intro02a.rb $ ruby intro02a.rb obj.xxx_methods == obj.singleton_class.xxx_instance_methods def print_module mod, ancestors = true if ancestors puts "#{mod.class.name.downcase} #{mod.name}" + " #{mod.ancestors.inspect}" else puts " #{mod.class.name.downcase} #{mod.name}" end mod.constants(false).each do |c| puts " const #{c.inspect}" end mod.public_instance_methods(false).each do |m| puts " #{m.inspect}" end if ancestors ancs = mod.ancestors[1..-1] ancs.each do |anc| print_module anc, false end end end print_module Class $ ruby intro03.rb def test a, b = 1, *c, d:, e: 2, **f, &g end p method(:test).parameters $ ruby intro04.rb ARG_TEMPLATE = { req: '%s', opt: '%s = <..>', rest: '*%s', key: '%s: <..>', keyreq: '%s:', keyrest: '**%s', block: '&%s' } def header mobj anprefix = 'arg' ancounter = 0 params = [] mobj.parameters.each do |param| if param.size == 2 name = param[1] else name = anprefix + ancounter.to_s ancounter += 1 end params << (ARG_TEMPLATE[param[0]] % name) end result = "#{mobj.name}(#{params.join(', ')})" if mobj.source_location result += " [#{mobj.source_location.join(':')}]" else result += " []" end result end def test a, b = 1, *c, d:, e: 2, **f, &g end puts header(method(:test)) puts header(method(:header)) puts header(method(:puts)) $ ruby intro05.rb def print_module mod title = "#{mod.class.name.downcase} #{mod}" if Class === mod && mod.superclass != nil title += " < #{mod.superclass}" end puts title puts " ancestors: #{mod.ancestors.join(', ')}" puts " constants:" mod.constants(false).each do |c| puts " #{c}" end puts " class methods:" mod.public_methods(false).each do |m| puts " #{header(mod.method(m))}" end puts " instance methods:" mod.public_instance_methods(false).each do |m| puts " #{header(mod.instance_method(m))}" end puts '' end ObjectSpace.each_object(Module) do |mod| print_module mod end class Alpha ALPHA = 1 class << self attr_accessor :beta end def alpha a, b = 0, *c p [a, b, c] end end ----------------------------------------------------------------------------------------------------------------- OpenGL для Android на Java и C++ Алексей Верижников public class OpenGLES20Activity extends Activity { private GLSurfaceView mGLView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Создаем экземпляр GLSurfaceView и устанавливаем его как контекст отображения для нашей активности или окна mGLView = new MyGLSurfaceView(this); setContentView(mGLView); } @Override protected void onPause() { super.onPause(); mGLView.onPause(); } @Override protected void onResume() { super.onResume(); mGLView.onResume(); } } public class MyGLSurfaceView extends GLSurfaceView { private final MyGLRenderer mRenderer; public MyGLSurfaceView(Context context) { super(context); // Создаем OpenGL контекст, который будет отображаться в активности setEGLContextClientVersion(2); // Создаем экземпляр класса рендеринга mRenderer = new MyGLRenderer(); setRenderer(mRenderer); // Режим рендеринга, где отображение новой картинки происходит при ее изменении setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } // Метод onTouchEvent вызывается при прикосновении к экрану устройства @Override public boolean onTouchEvent(MotionEvent e) { float x = e.getX(); float y = e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: { … } } return true; } } public class MyGLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "MyGLRenderer"; private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16]; private final float[] mRotationMatrix = new float[16]; @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Инициализация данных при создании контекста // OpenGL GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); } @Override public void onDrawFrame(GL10 unused) { // Очистка экрана GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT| GLES20.GL_DEPTH_BUFFER_BIT); // Генерируем матрицу камеры Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); // Перемножаем видовую матрицу и матрицу камеры для получения необходимой матрицы отображения Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); // Отображаем нашу сцену mSquare.draw(mMVPMatrix); // Создаем матрицу поворота Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f); Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); } @Override public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; // Меняем видовую матрицу в соответствии с новыми параметрами Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); } // Полезная функция отображения и проверки ошибок public static void checkGlError(String glOperation) { int error; while ((error = GLES20.glGetError()) != GLES20. GL_NO_ERROR) { Log.e(TAG, glOperation + ": glError " + error); throw new RuntimeException(glOperation + ": glError " + error); } } } extern "C" { JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height); JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj); }; JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height) { setupGraphics(width, height); } JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj) { renderFrame(); } package com.android.gl2jni; public class GL2JNILib { static { System.loadLibrary("gl2jni"); } public static native void init(int width, int height); public static native void step(); } LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libgl2jni LOCAL_CFLAGS := -Werror LOCAL_SRC_FILES := gl_code.cpp LOCAL_LDLIBS := -llog -lGLESv2 include $(BUILD_SHARED_LIBRARY) private void init(boolean translucent, int depth, int stencil) { setEGLContextFactory(new ContextFactory()); setRenderer(new Renderer()); } public void onDrawFrame(GL10 gl) { GL2JNILib.step(); } public void onSurfaceChanged(GL10 gl, int width, int height) { GL2JNILib.init(width, height); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Do nothing. } @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); mView = new GL2JNIView(getApplication()); setContentView(mView); } -----------------------------------------------------------------------------------------------------------------