git对象存储

之前提到当存储数据内容时,同时会有一个文件头被存储起来。我们花些时间来看看 Git 是如何存储对象的。你将看来如何通过 Ruby 脚本语言存储一个 blob 对象 ,有必要了解一下对象是如何被存储的。以git设计哲学中的test1.txt为例分析blob对象如何被计算校验和?如何被存储?是否和直接调用git命令的结果一致?

sha-1校验和计算

我们需要验证通过ruby计算出来的检验和与这个一致。

为了验证,新建一个git仓库

$ mkdir blobtest
$ cd blobtest

$ git init
Initialized empty Git repository in /Users/lyc/Desktop/tg/.git/

同样新建一个文件test1.txt,内容为test1,并把它加入暂存区

$ echo test1 > test1.txt
$ git add test1.txt

 

gitt使用’blob ‘ + len(content) + ‘\0’ + content作为文件内容
blob表示对象类型为blob类型,

len表示内容的长度

\0为空字节

其中’blob ‘ + len(content) + ‘\0’ 来组成一个header,然后再将这个header与真正的内容拼接起来,并计算拼接后的新内容的 SHA-1 校验和。

使用 irb 命令进入 Ruby 交互式模式:

$ irb
irb(main):001:0> content = “test1\n”
=> “test1\n”
irb(main):002:0> header = “blob #{content.length}\0”
=> “blob 6\u0000”
irb(main):003:0> store = header + content
=> “blob 6\u0000test1\n”
irb(main):004:0> require ‘digest/sha1’
=> true
irb(main):005:0> sha1 = Digest::SHA1.hexdigest(store)
=> “a5bce3fd2565d8f458555a0c6f42d0504a848bd5”

可见计算出来的校验后与刚开始设定的校验和是一致的。

 

git对象存储

在git设计哲学中我们了解到test1.txt被git add命令添加到git仓库后,存储的路径如下

.git/
|–index
|–objects
| |–a5
| …

git设计哲学

刚开始使用git的时候,总想拿git来和cvs或者svn来作对比,但不久后发现这个想法本身就是错的,git完全就是另外一种物种,一种本属于未来的物种。它的对象存储方式,快照,分支等,都是完全不同的。

相信每个使用git的人,都想了解git内存文件的存储对象,快照,提交在历史和分支等内部的原理。都想知道它是否有传说中的那么强大?

Git 对象

先从本地创建一个空git仓库开始

$ mkdir test
$ cd test
$ git init
Initialized empty Git repository in /Users/lyc/Desktop/test/.git/

这时会发现目录下只有一个.git文件夹,进去后长这样

.git/
|–HEAD
|–config
|–description
|–hooks
| |–applypatch-msg.sample
| |–commit-msg.sample
| |–post-commit.sample
| |–post-receive.sample
| |–post-update.sample
| |–pre-applypatch.sample
| |–pre-commit.sample
| |–pre-rebase.sample
| |–prepare-commit-msg.sample
| |–update.sample
|–info
| |–exclude
|–objects
| |–info
| |–pack
|–refs

description文件仅供GitWeb使用,不用关心它。
config文件包含了项目特有的配置选项,如最常用的用户名和邮箱。
info目录保存了一份不希望在 .gitignore 文件中管理的忽略模式 (ignored patterns) 的全局可执行文件。这个用得比较少,也不用太关心。
hooks目录保存了客户端或服务端钩子脚本,一般我们都是用默认的,很少改,也不用太关心。

因此,我们需要重点关心另外四个重要的文件或目录:HEAD和index文件,objects和refs目录,因为它们是Git的核心:

objects 目录存储所有数据内容。
refs 目录存储指向数据 (分支) 的提交对象的指针。
HEAD 文件指向当前分支。
index 文件保存了暂存区域信息。

刚初使化的一个 Git 仓库, objects 目录是空的:

$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack

Git 初始化了 objects 目录,同时在该目录下创建了 pack 和 info 子目录,但是该目录下没有其他常规文件

接下来,我们新建一个文件test1.txt,内容为test1,并把它加入暂存区

$ echo test1 > test1.txt
$ git add test1.txt

发现.git目录下多了2个文件,且内容都为字节码:

.git/
|–index
|–objects
| |–a5
| | …

android本地定时通知

android本地通知略有不同,分为立即触发和延时触发

1.即时通知

android默认的Notification为立即触发

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClass(_gameActivity, _gameActivity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
PendingIntent content = PendingIntent.getActivity(context, 0, intent, 0);
final NotificationManager notiMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final Notification noti = new Notification(R.drawable.icon, notiResult.getPayload(), System.currentTimeMillis());
String app_name = _gameActivity.getResources().getString(R.string.app_name);
noti.setLatestEventInfo(context, app_name, notiResult.getPayload(), content);

notiMgr.notify(atomicInteger.incrementAndGet(), noti);

 

2.延时触发

想让一定时间后再触发通知,其实是用系统的AlarmManager来实现的。

具体的AlarmManager解释参考

http://yuanzhifei89.iteye.com/blog/1131523

http://blog.csdn.net/ryantang03/article/details/9317499

添加一个ALARM_SERVICE

/*
* name:通知名字,作为通知id使用
* content:通知内容
* time:倒时时(秒)
* */
public static void addLocalNotication(String name, String content, int time)
{
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.SECOND, (int) time);

Activity activity = _gameActivity;
Intent intent = new Intent(activity, NotificationReceiver.class);
intent.setClass(activity, NotificationReceiver.class);
intent.setData(Uri.parse(name));
intent.putExtra(“msg”, “play_hskay”);

intent.putExtra(“content”, content);
PendingIntent pi = PendingIntent.getBroadcast(activity, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager am = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
}

 

添加一个系统通知类,用于在倒计时间到时,接收系统轮询通知

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import …